快速设置:我想在程序中传递字符串作为指针和大小.我有一个String类和一个用户定义的文字用于构造文字字符串:
struct String { const char *ptr; size_t sz; };
inline constexpr String operator "" _string(const char *s, size_t sz) {
return {s, sz};
}
int main() {
auto s = "hello"_string;
s.ptr[0]; //<-- is this access guaranteed to work?
}
Run Code Online (Sandbox Code Playgroud)
标准是否指定传递给我的用户定义的文字运算符的参数具有静态持续时间?即上面的代码实际上等同于写作:
int main() {
String s{"hello", 5};
}
Run Code Online (Sandbox Code Playgroud)
或者当我使用用户定义的文字时,是否允许编译器/链接器给我留下悬空指针?
(N4527的第2.13.8节似乎没有说明用户定义的字符串文字运算符的参数的存储类的主题.任何指向标准的相应部分的指针都将不胜感激.)
这是一个关于内联变量及其在多个翻译单元中的唯一性的问题.请考虑以下代码,它们跨两个翻译单元共享字符串文字:
文件hdr.h:
inline const char* const str = "hello world";
Run Code Online (Sandbox Code Playgroud)
文件tu0.cpp:
#include <cstdio>
#include "hdr.h"
void foo()
{
printf("tu0: &str=%p, str=%p\n", &str, str);
}
Run Code Online (Sandbox Code Playgroud)
文件tu1.cpp:
#include <cstdio>
#include "hdr.h"
extern void foo();
int main()
{
foo();
printf("tu1: &str=%p str=%p\n", &str, str);
}
Run Code Online (Sandbox Code Playgroud)
为了完整性,这是我如何编译这些(在Linux,64位,binutils 2.28):
$ CXX -c -std=c++1z tu0.cpp -o tu0.o
$ CXX -c -std=c++1z tu1.cpp -o tu1.o
$ CXX -std=c++1z tu*.o -o a.out
Run Code Online (Sandbox Code Playgroud)
使用CXX = clang-4.0,str和&str是相同的:
tu0: &str=0x400608 str=0x4005f9
tu1: &str=0x400608 str=0x4005f9
Run Code Online (Sandbox Code Playgroud)
但是使用g ++版本7.1和7.2,我得到了令人惊讶的结果:
tu0: &str=0x4005d8 str=0x4005b4
tu1: &str=0x4005d8 …Run Code Online (Sandbox Code Playgroud) 请考虑以下代码,该代码具有无法访问的无法访问undefinedFunction.
void undefinedFunction();
template <bool b = false>
void foo()
{
static_assert(b == false);
if (b)
undefinedFunction();
}
int main()
{
foo();
}
Run Code Online (Sandbox Code Playgroud)
GCC在没有投诉的情况下编译和链接.有了static_assert,很难看出编译器如何做出不同的事情,但标准对此有什么要说的吗?如果static_assert删除怎么办?编译器是否有义务删除分支,或者它实际上是否会发出一条无法访问的调用指令,这会导致链接器抱怨?