此代码编译并执行.我知道在第一种情况下我们有未定义的行为.但在第二种情况下究竟发生了什么?
#include <string>
#include <iostream>
#include <cstdio>
std::string foo() {
return "HELLO";
}
void bar(const char *p) {
std::printf("%s\n", p);
}
int main() {
// FIRST CASE:
// I know this is bad, because after the assignment
// the variable returned by foo() is destroyed and we
// have a bad reference.
const std::string &s = foo();
bar(s.c_str());
// SECOND CASE:
// But what about that ? I don't know exactly if the
// object is alive after the call to c_str()
bar(foo().c_str());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
GCC输出在两种情况下都是"HELLO",但我认为这是因为它没有清理原始内存.
在第二种情况下,临时对象究竟被销毁了吗?
Tar*_*ama 11
实际上,这两种情况都没问题.
在第一种情况下,将临时绑定到const引用会将其生命周期延长到s.因此在main退出之前不会被销毁.
在第二种情况下,临时在包含它的完整表达式结束后被销毁.在这种情况下,它是函数调用.如果你将C字符串存储在任何已经过时的状态bar,然后尝试访问它,那么你应该是一个具有未定义行为的日期.
这两种情况都有明确的定义。要查看有问题的情况,请将结果存储c_str()到std::string被破坏之后:
#include <string>
#include <cstdio>
std::string foo() {
return "HELLO";
}
void bar(const char *p) {
std::printf("%s\n", p);
}
int main() {
{
// FIRST CASE:
// This is okay, because the reference is const, so the object is alive
// until s goes out of scope.
const std::string &s = foo();
bar(s.c_str());
}
{
// VARIANT FIRST CASE:
// This is bad; the pointer is dangling
const char *s = foo().c_str();
bar(s);
}
{
// SECOND CASE:
// Is the object still alive after the call to c_str()? Yes, it's alive
// until after bar() has returned.
bar(foo().c_str());
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我在 Valgrind 下运行它时,它仅针对变体情况(带有const char *s)给出错误:
==9981== Invalid read of size 1
==9981== at 0x4C2E0E2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9981== by 0x543EC7B: puts (ioputs.c:36)
==9981== by 0x400937: bar(char const*) (37946437.cpp:9)
==9981== by 0x4009AA: main (37946437.cpp:25)
==9981== Address 0x5aabcf8 is 24 bytes inside a block of size 30 free'd
==9981== at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9981== by 0x4F058FD: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22)
==9981== by 0x40099E: main (37946437.cpp:24)
Run Code Online (Sandbox Code Playgroud)