因此,我们在Linux上遇到了一次失败的测试,我认为这是由于我对有关引用内置文字的指针的有效性的错误假设所致。该代码类似于以下伪代码:
auto obj = func( 'c', "str" ); // (1)
big_type big_object; // (2)
在(1),func()
返回一个对象,该对象存储一个指向字符文字的 const
指针和一个指向字符串文字的指针。在调试器中的检查表明两者都是正确的。
在(2),调试显示'c'
中的 const char*
所引用的内存中的obj
被覆盖。
提示表明,int
和double
文字也会发生这种情况。在GCC 5.4.1上会发生这种情况,在GCC 4.1.2上不会发生。
使用C ++已有25年以上的经验,我学会了假设,通常,编译器是对的,而我是错的。所以我也在这里做
但是,尽管我知道,如果这仅涉及小型内置类型的文字,我可以解决此问题(通过复制它们而不是引用它们),如果这可能发生于任意大小的对象({{1 }}),我们还有一个很大的问题。
那么有人可以解释一下这方面的确切规则吗?
答案 0 :(得分:4)
来自[{expr.prim.literal§1]:
文字是主要表达方式。其类型取决于其形式。字符串文字是左值;所有其他文字都是prvalue。
有关这些左值的更高精度,请参见[lex.string§16]:
计算 string-literal 会生成具有静态存储持续时间的字符串文字对象,该对象根据上述指定的字符进行初始化。 [...]
这直接解决了这个问题:字符串文字是唯一具有静态存储持续时间的文字,因此可以被超出它们出现的表达式的指针引用。
答案 1 :(得分:2)
假设func
定义如下:
some_class_type func(const char& ch, const char* str)
{
some_class_type some_object;
some_object.pch = &ch;
some_object.pstr = str;
return some_object;
}
然后,您使用&ch
存储指向临时变量的指针。
ch
的生命周期不是不是完整程序,仅直到完整表达式(即调用func('c', "str")
)的结尾,然后是临时变量将不复存在,而您将留下一个流浪指针。
对于单个字符,例如对于单个整数或浮点值,几乎不需要使用指向它们的指针。存储值。
答案 2 :(得分:1)
字符串文字在程序的整个生命周期中一直存在。字符文字不是,因为它们实际上只是整数,并且不接受对字符串的任何特殊处理。
换一种方式来看:您的函数接收两个参数:一个是字符值,另一个是指向字符串文字的指针。复制指向字符串的指针很好,但是创建指向作为参数传递的值的指针是不可行的。与创建指向字符串的指针的麻烦一样。函数调用完成后,函数参数将被销毁。在字符的情况下,这意味着字符不见了;而在指针到字符串的情况下,您已经复制并保存了它。
答案 3 :(得分:1)
对于确切的规则,在string literals上指出以下句子可能就足够了(尽管昆汀的标准报价显然更权威)。
字符串文字具有静态的存储期限,因此在程序生命周期内存在内存中
other types of literal中的任何一个都不存在。
查看它的另一种方法是重新检查您的代码
object func(char c, const char *s)
{
return object{&c, s};
}
,请注意,字符串文字不按值传递。因为(一旦它衰减为指针),您只是传递第一个字符的地址-该数组必须至少保持一段时间有效,并且由于无法知道生命周期应该是什么,因此静态持续时间是理智的默认设置。