我正在尝试理解C++17标准中的生存期保证,特别是针对保证复制省略。 让我们从一个例子开始
std::string make_tmp();
std::string foo() {
return std::string{make_tmp().c_str()};
}
我对正在发生的事情的理解:
make_tmp
创建一个临时字符串,我们将其称为t
;foo
返回(不必要地创建的)t
的临时副本(即c_str
)。
标准(包括C++17之前的版本)保证了t
的寿命直到完整的返回表达式被评估完成。
因此,安全地创建t
的临时副本(以便返回)。
现在,复制省略开始生效;更具体地说,是第一段C++17块中的第二个项目:
在函数调用中,如果返回语句的操作数是prvalue,并且函数的返回类型与该prvalue的类型相同。
因此,在这种情况下,临时副本甚至根本不会被创建。
跟进问题:
即使被保证省略,返回的临时副本仍然意味着
t
有足够长的寿命吗?考虑下面给出的
foo
变种。 我假设不再需要复制省略(但是非常可能)。 如果不会省略复制,则标准通过上述论点保证了我们的权利。 在省略复制的情况下,尽管return
表达式的类型与foo
的返回类型不同,标准仍然保证t
具有足够的生命周期吗?
foo
变种:
std::string foo() {
return make_tmp().c_str();
}
我希望了解标准所纯粹暗示的保证。
请注意,我知道两个foo
版本“工作”(即在使用各种编译器测试自定义类时都没有悬空指针问题)。
return make_tmp().c_str();
即使在 C++17 之前也是有效的。 (该语句返回make_tmp()
函数创建的临时对象的指针,表示该语句可以在旧版的 C++ 中正常运行。) - Jarod42make_tmp().c_str()
等同于std::string(make_tmp().c_str())
,隐式地进行了复制省略。 - Yuki