如果我有以下代码:
{
UnicodeString sFish = L"FISH";
char *szFish = AnsiString(sFish).c_str();
CallFunc(szFish);
}
那么创建的临时AnsiString的范围是什么,以及szFish指向有效数据的时间有多长?它仍然对CallFunc函数有效吗?
它的范围只是一行,还是整个块?
答案 0 :(得分:5)
szFish
之前, CallFunc()
无效,因为AnsiString
是一个立即被破坏的临时对象,szFish
指向其内部缓冲区已被删除。
确保AnsiString
实例对CallFunc()
的调用有效。例如:
CallFunc(AnsiString(sFish).c_str());
答案 1 :(得分:4)
我会替换:
char *szFish = AnsiString(sFish).c_str();
使用:
AnsiString as(sFish);
char *szFish = as.c_str();
我不知道AnsiString
类,但在您的代码中,析构函数会在您调用CallFunc()
之前触发,并且很可能会释放您使用*szFish
指向的字符串。当您使用堆栈上的“命名”对象替换临时对象时,其生命周期将延长到定义它的块的末尾。
答案 2 :(得分:2)
C ++ 11标准$ 12.2.3说:
当实现引入类的临时对象时 有一个非平凡的构造函数(12.1,12.8),它应该确保a 为临时对象调用构造函数。同样, 析构函数应该被称为临时的非平凡的 析构函数(12.4)。 临时对象作为最后一步被销毁 评估(词法上)包含的全表达式(1.9) 创建它们的地方。即使进行评估也是如此 以抛出异常结束。价值计算和副作用 销毁临时对象只与 完整表达,而不是任何特定的子表达式。
(强调我的)
还有其他注意事项,但在这种情况下它们并不适用。在您的情况下,完整表达式是本声明的指示部分:
char *szFish = AnsiString(sFish).c_str();
// ^^^^^^^^^^^^^^^^^^^^^^^^^
因此,分配了即时szFish
,将调用临时对象的析构函数(即AnsiString(sFish)
),并释放其内部内存表示(c_str()
指向的位置) 。因此,szFish
将立即成为悬空指针,任何访问都将失败。
你可以说
来解决这个问题CallFunc(AnsiString(sFish).c_str());
相反,在这里,临时将在完整表达式之后(再次)在;
)之后被销毁({1}}并且CallFunc
将能够读取原始字符串。
答案 3 :(得分:1)
在这种情况下,AnsiString的范围是“从调用c_str()之前,直到紧接着。”以这种方式思考可能会有所帮助:
char *szFish;
{
AnsiString tmpString(sFish);
szFish = tmpString.c_str();
}