C++:嵌套时,两个单独的函数返回不同的结果吗?
我试图将一个十六进制编码的字符串转换成一个包含解码字符串的const char *缓冲区。 为此,我有一个函数(string hex_decode(string hex_input)
)接受字符串并对其进行解码。
自行测试功能几次后,我尝试了以下调用:C++:嵌套时,两个单独的函数返回不同的结果吗?
const char* hex_decoded_c_str = hex_decode(input).c_str();
,看到它返回完整的胡言乱语! 在努力调试问题,我把它分成两个语句,就像这样:
string hex_decoded_string = hex_decode(input);
const char* hex_decoded_c_str = hex_decoded_string.c_str();
这一次,它完美地工作!
我很困惑,有没有人知道可能会导致这样的事情?
与
const char* hex_decoded_c_str = hex_decode(input).c_str();
你正在做一个参照string
临时对象(返回值),这是无效的内部表示,当hex_decode(input)
超出范围,则c_str()
电话之后。
用另一种方法,您复制string
对象,使该引用在您的范围内有效。
*“临时对象[...],它在下一行中无效。”* - 这是不准确的。作为评估包含创建点的完整表达式的最后一步,临时对象被销毁。如果在完整表达式后面的同一行上有代码,则临时文件已经在同一行上死了**。最好不要使用*“行”*的概念,这对C++编译器来说是毫无意义的。 – IInspectable
*“指令”*不是在C++中使用的术语。它通常归因于汇编编程。仍然不准确是不准确的改进。 – IInspectable
好的,目前的措辞对你更好吗? –
c_str()
方法返回的指针在std::string
实例被销毁后变为无效。
string hex_decode(string hex_input)
返回临时对象string
。 c_str()
将一个指针返回到该字符串对象的私有部分。一旦临时死亡(在完整表达式的末尾),该指针指向无法访问的内存。这就是所谓的未定义的行为。
要解决此问题,请将返回值复制到本地string
对象中,或者通过将其绑定到const string&
引用来延长临时对象的生存期。返回值c_str()
的有效性与其被调用对象的生命周期相关。遵守不能由编译器,库或运行时强制执行。这是开发者需要确定的事情。
仅供参考,请参阅Lifetime。
原型string hex_decode(string hex_input)
表示一个新的字符串对象总是由hex_decode
返回。标准的
段落12.2#3
说:
临时对象被销毁作为评价全表达式(词法)包含了他们所创建点的最后一步。
此外c_str()
返回一个指向内的字符串对象东西。
当读取文档c_str()
和data()
(现在执行同样的功能),你可以推断,从该线(见here或21.4.7.1#1
):
c_str() + i == &operator[](i)
为每i in [0, size()]
。
因此:
一旦c_str()
结束还有;
和hex_decode()
返回的临时字符串必须被销毁。在销毁期间,它释放底层字符数组。
但是,为了保留字符数组,不需要复制临时字符串。 12.2#4,5
:
有两种情况,临时状态在与完整表达式结尾不同的点处销毁。 ...第二个上下文是当引用绑定到临时的时候。
所以你可以绑定一个常量引用到临时对象,并节省拷贝构造函数调用:
const string & hex_decoded_string = hex_decode(input);
const char* hex_decoded_c_str = hex_decoded_string.c_str();
@Biffen不再。 –
我敢肯定,你在hex_decode中创建了一个本地字符串对象。由于string类具有深度复制赋值运算符,因此当您返回字符串时,它将被复制到hex_decoded_string对象中,而不会出现内存问题。在前一种情况下,您正在将hex_decoded_c_str指向堆栈内存,这是不正确的情况 –