欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用c++11 constexpr時(shí)遇到的坑詳解

 更新時(shí)間:2021年05月16日 10:22:50   作者:apocelipes  
c++11 constexpr將變量聲明為constexpr類(lèi)型以便由編譯器來(lái)驗(yàn)證變量是否是一個(gè)常量表達(dá)式,這篇文章主要給大家介紹了關(guān)于使用c++11 constexpr時(shí)遇到的坑,需要的朋友可以參考下

最近在使用constexpr的時(shí)候無(wú)意中踩了個(gè)小坑。

下面給個(gè)小示例:

#include <iostream>

constexpr int n = 10;
constexpr char *msg = "Hello, world!";

int main()
{
    for (auto i = 0; i < n; ++i) {
        std::cout << msg << std::endl;
    }
}

constexpr應(yīng)該是大家很熟悉的東西了,也是最常用的c++11新特性之一。和宏相比除了更強(qiáng)的類(lèi)型安全之外,constexpr還帶來(lái)了編譯期計(jì)算。

上面的代碼相當(dāng)簡(jiǎn)單,我們循環(huán)輸出“Hello, world!”這個(gè)字符串10次。

這么簡(jiǎn)單的代碼還有討論的必要嗎?一開(kāi)始我也是這么想的,然而當(dāng)我們編譯運(yùn)行的時(shí)候卻會(huì)得到下面這樣的警告:

$ g++ --version
                      
g++ (GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


$ g++ -std=c++17 -Wall -Wextra test.cpp

test.cpp:4:23: 警告: ISO C++ forbids converting a string constant to ‘char*' [-Wwrite-strings]
    4 | constexpr char *msg = "Hello, world!";
      |                       ^~~~~~~~~~~~~~~

這段信息的意思是c++不允許把字符串字面量賦值給char*。

然而對(duì)于constexpr,文檔中是這么寫(xiě)的:

A constexpr specifier used in an object declaration implies const.

這里的object你可以理解為變量,意思是constexpr修飾的變量都會(huì)隱式添加一個(gè)const限定符。

也就是說(shuō):

// T 是任意類(lèi)型
constexpr T a = xxx;
// 不考慮其他因素,在類(lèi)型上等價(jià)于:
T const a = xxx;

我們這里的T實(shí)際上可以填任意類(lèi)型,包括指針。這不是說(shuō)明我們的指針變量有const嗎?

眼尖的讀者大概已經(jīng)知道答案了:constexpr添加的是頂層const。

所以我們的代碼實(shí)際上是這樣的:

// 原本的代碼
constexpr char *msg = "Hello, world!";
// 實(shí)際上的效果
char * const msg = "Hello, world!";

下面一行的msg實(shí)際上是一個(gè)指向char的指針常量,而我們可以通過(guò)它任意修改被指向的字符串(當(dāng)然這是未定義行為)。指針常量意味著我們不能把這個(gè)指針重新指向其他的對(duì)象,這個(gè)const作用在指針本身上,因此叫做頂層const。

而字符串常量的類(lèi)型是const char[N],在表達(dá)式里退化為const char *,這表示一個(gè)指向常量字符串的指針,這里的const的底層的,因?yàn)樗饔糜诒恢赶虻膶?duì)象而不是我們的指針自身。

對(duì)于頂層const,賦值的時(shí)候是可以被去除的,而底層const則不行,這就是為什么編譯器會(huì)彈出警告的原因了。

正確的做法也很簡(jiǎn)單,牢記constexpr不是const的等價(jià)替代品,它只會(huì)添加頂層const,不會(huì)添加底層const。

所以constexpr的字符串常量應(yīng)該這樣寫(xiě):

constexpr const char *p = "Hello, world!";

或者你的編譯環(huán)境支持c++17,我更推薦你這樣寫(xiě):

#include <string_view>

constexpr std::string_view msg = "Hello, world!";

使用string_view之后就不會(huì)出現(xiàn)上面的頂層/底層const的坑了。所以在現(xiàn)代c++里能不用裸指針就盡量不要用。

參考

https://stackoverflow.com/questions/54258241/warning-iso-c-forbids-converting-a-string-constant-to-char-for-a-static-c

總結(jié)

到此這篇關(guān)于使用c++11 constexpr時(shí)遇到坑的文章就介紹到這了,更多相關(guān)c++11 constexpr坑內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++遍歷某個(gè)文件夾下面的子文件夾及其所有文件

    C++遍歷某個(gè)文件夾下面的子文件夾及其所有文件

    這篇文章主要介紹了C++獲取某個(gè)文件夾下面的子文件夾及其所有文件,需要的朋友可以參考下
    2021-07-07
  • C語(yǔ)言數(shù)組指針的小例子

    C語(yǔ)言數(shù)組指針的小例子

    這篇文章介紹了,用c語(yǔ)言實(shí)現(xiàn)的一個(gè)數(shù)組指針的小例子,有需要的朋友可以參考一下
    2013-07-07
  • C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單反彈球消磚塊游戲

    C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單反彈球消磚塊游戲

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單反彈球消磚塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Qt控件點(diǎn)擊消息獲取的方法詳解

    Qt控件點(diǎn)擊消息獲取的方法詳解

    本文將利用Qt中的QLabel、QPushButton這兩個(gè)控件,為大家詳細(xì)介紹一下Qt控件點(diǎn)擊消息獲取的方法,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2022-06-06
  • C++11的右值引用的具體使用

    C++11的右值引用的具體使用

    這篇文章主要介紹了C++11的右值引用的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • QT5連接MySQL實(shí)現(xiàn)增刪改查

    QT5連接MySQL實(shí)現(xiàn)增刪改查

    這篇文章主要為大家詳細(xì)介紹了QT5如何連接MySQL實(shí)現(xiàn)增刪改查功能,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的可以了解一下
    2022-12-12
  • VScode中添加頭文件和源文件(C/C++)的方法

    VScode中添加頭文件和源文件(C/C++)的方法

    使用VSCode編譯C/C++時(shí),會(huì)存在找不到頭文件的情況,下面這篇文章主要給大家介紹了關(guān)于VScode中添加頭文件和源文件(C/C++)的相關(guān)資料,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • C++中vector的實(shí)現(xiàn)方法示例詳解

    C++中vector的實(shí)現(xiàn)方法示例詳解

    這篇文章主要介紹了C++中vector實(shí)現(xiàn)的相關(guān)資料,vector是C++中重要的容器之一,底層通過(guò)三個(gè)迭代器實(shí)現(xiàn),分別是_start,?_finish,?和_end_of_storage,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-10-10
  • static全局變量與普通的全局變量的區(qū)別詳細(xì)解析

    static全局變量與普通的全局變量的區(qū)別詳細(xì)解析

    以下是對(duì)static全局變量與普通的全局變量的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2013-09-09
  • 淺談C++性能榨汁機(jī)之偽共享

    淺談C++性能榨汁機(jī)之偽共享

    使給定內(nèi)存位置被一個(gè)線(xiàn)程所訪(fǎng)問(wèn),可能還是會(huì)有乒乓緩存的存在,是因?yàn)榱硪环N叫做偽共享(false sharing)的效應(yīng)。即使數(shù)據(jù)存儲(chǔ)在緩存行中,多個(gè)線(xiàn)程對(duì)數(shù)據(jù)中的成員進(jìn)行訪(fǎng)問(wèn)時(shí),硬件緩存還是會(huì)產(chǎn)生乒乓緩存。本文將介紹C++中的偽共享
    2021-06-06

最新評(píng)論