使用临时字符串的std::string::c_str()方法是否安全?

72
以下的C++代码是否格式良好?
void consumer(char const* p)
{
  std::printf("%s", p);
}

std::string random_string_generator();

consumer(random_string_generator().c_str());

我对它的问题是,在创建临时的std::string对象并获取c_str()指针之后,没有任何阻止std::string对象被销毁的措施,除非我错了。
根据标准,这段代码是否符合规范?在我使用g++进行测试时,它是有效的。
3个回答

91
std::string::c_str()返回的指针指向由字符串对象维护的内存,它保持有效直到对字符串对象调用非const函数或销毁字符串对象。你关心的字符串对象是一个临时对象,在完整表达式的末尾才会被销毁,既不早于也不晚于此处。在你的情况下,完整表达式的末尾在调用consumer之后,因此你的代码是安全的。如果consumer将指针保存在某个地方以便稍后使用,则不安全。
自C++98以来,临时变量的生命周期已被严格定义。在此之前,这取决于编译器,您编写的代码无法在g++(大约在1995年之前)中运行 - g++几乎立即在标准委员会投票通过后更改了这一点。 (那时还没有std::string ,但同样的问题会影响任何用户编写的字符串类。)

如果在后续语句中(仍在函数内部,但不是第一条语句)使用“c_str()const char *”,会发生什么? 这会导致指针悬空吗? - Alex Gidan
我自己回答...在这种情况下,它将是无效的: §12.2 ...临时对象在评估包含它们创建点(词法上)的完整表达式(1.9)的最后一步中被销毁。即使该评估以抛出异常结束,这也是正确的。 - Alex Gidan
std::string temp = random_string_generator().c_str();假设temp是正确的吗? 因为从random_string_generator()返回的字符串的生命周期将持续到表达式结束。 - Ayush Pant
@AyushPant,是的。在初始化temp并复制字符时,const char*是有效的。但为什么不直接移动函数返回的字符串呢? - Bolpat

25

临时的std::string寿命延伸到consumer返回的一点,因此可以直接从consumer内部使用该字符串上的任何内容。 不可以的是存储c_str返回的值并尝试稍后使用它(临时值将被销毁,我们只能猜测指针的另一端会发现什么)。


1
你能提供关于C++03或C++11标准的提示吗? - user1095108
6
临时对象的生命周期在§12.2中定义。(第12节名为“特殊成员函数”,这不是你期望查找临时对象生命周期的准确位置,但就是它所在的地方。) - James Kanze
1
@user1095108和函数参数的生命周期可以从c++03标准的§3.2.2和§3.7.2中获得。 - juanchopanza

6
函数random_string_generator()返回的临时变量可以在consumer()函数中安全使用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接