C++ 将本地字符串参数作为对const的引用传递到constexpr函数中?为什么这是合法的?
constexpr函数只接受文本类型的参数。类字符串的对象本身不是文本类型,而是指针(标量类型)或引用是文本类型。因此,对字符串的引用是一种文字类型 此外,如果constexpr函数的参数也是常量表达式,则它只返回常量表达式 “如果scale*函数的参数为 是一个常量表达式,但除此之外:“C++ 将本地字符串参数作为对const的引用传递到constexpr函数中?为什么这是合法的?,c++,c++11,constexpr,C++,C++11,Constexpr,constexpr函数只接受文本类型的参数。类字符串的对象本身不是文本类型,而是指针(标量类型)或引用是文本类型。因此,对字符串的引用是一种文字类型 此外,如果constexpr函数的参数也是常量表达式,则它只返回常量表达式 “如果scale*函数的参数为 是一个常量表达式,但除此之外:“ 来源:C++入门,第五版< /P> 在本例中,比例较短() 现在,我在这里将字符串的两个引用传递给一个constexpr函数,该函数不保留在固定地址(全局或静态),而是保留在变量地址(本地)。因此,这两个参数
来源:C++入门,第五版< /P> 在本例中,比例较短() 现在,我在这里将字符串的两个引用传递给一个constexpr函数,该函数不保留在固定地址(全局或静态),而是保留在变量地址(本地)。因此,这两个参数不应该是常量表达式。
constexpr函数的结果被分配给constexpr bool 运行:
$ ./ex646
address of shrt 0x7ffd39e41a50 # every time different
address of longer 0x7ffd39e41a40 # every time different, always 0x10 more than &shrt
shrt is shorter
string 0
string& 1
string* 1
编译器如何比较两个字符串的地址?它们在程序的每个运行时都是不同的,而它们的相对位置保持不变。这种用法的关键是,至少它们彼此的相对位置保持不变吗
更新2015-08-12在撰写本文时,这看起来像是ISO标准中的“常量评估规则中的错误”(如果我错了,请纠正我)。请参见isocpp.org列表。因此,这不应该是GCC和CLANG中的编译器错误
谢谢,戴普 字符串的地址是堆栈对象的地址,而不是字符串正在包装的底层指针。每次运行时地址可能不同,但编译器每次都会以相同的方式将变量加载到内存中,因此比较将始终产生相同的结果 注意:不同的编译器可能以不同的方式对变量排序,因此此代码不可移植 注2:为相等(=,!=)比较指针是为相同类型的指针定义的行为。如果出现以下情况,则未指定尝试与关系运算符(,=)进行比较: 同一类型的两个指针p和q指向不同的对象,这些对象不是同一对象的成员或同一数组的元素,也不是指向不同的函数,或者如果其中只有一个为null
据我所知,这看起来像某种编译器扩展或bug。C++11通过缺陷报告进行了调整,以允许将引用视为文字类型,而不管它引用的变量是否为文字类型。但是,引用常量表达式应该引用具有静态存储持续时间的对象,类似于地址常量表达式 C++11标准草案告诉我们指针可以被视为相等的情况: 如果相同类型的两个指针比较相等,则 只有当它们都为null时,它们都指向同一个函数,或者都表示相同的地址(3.9.2) 因此,在您的情况下,编译器可以简单地推断出
是哪种情况=
属于这种情况,但我没有看到一个可以避免这种情况下的常量表达式要求的切口
参考章节5.19
[expr.const]告诉我们:
引用引用类型的变量或数据成员的id表达式,除非该引用具有
在初始化之前,使用常量表达式初始化
对其进行了修改,修改如下:
引用引用类型的变量或数据成员的id表达式,除非该引用具有
在初始化之前,以及
- 它是用常量表达式或
- 它是一个对象的非静态数据成员,其生存期开始于对e的求值
3.9
[basic.types]一节,该节在N3337
C++11标准草案中指出:
如果类型是:
[……]
- 引用文本类型的引用类型;或
- 参考类型;或
谢谢在接受你的答案之前,最后再问一个问题。这不是实现定义的行为?如果我没记错的话,比较地址看哪个更大实际上是未定义的行为!更实际的情况是,一些编译器会在堆栈上分配局部变量,从最大地址开始,然后变小,而不是从最小地址开始,然后变大。当然,它可以做任何它想做的事(除了给他们相同的地址)谢谢。因此,将指针仅用于相等似乎是一种行为定义。此外,我在一个答案中看到了这个链接,它在几分钟前被删除了(为什么?):如果用亲戚测试它
$ g++ -o ex646 ex646.cpp -std=gnu++11 -Wall -Wpedantic
$ ./ex646
address of shrt 0x7ffd39e41a50 # every time different
address of longer 0x7ffd39e41a40 # every time different, always 0x10 more than &shrt
shrt is shorter
string 0
string& 1
string* 1