如何理解“临时对象被销毁作为评估完整表达式的最后一步”?有人可以通过一些简单的例子说清楚吗?
Posted
技术标签:
【中文标题】如何理解“临时对象被销毁作为评估完整表达式的最后一步”?有人可以通过一些简单的例子说清楚吗?【英文标题】:How to comprehend "Temporary objs are destroyed as the last step in evaluating the full-expression"?Could anyone make it clear by some simple example? 【发布时间】:2020-05-24 00:05:30 【问题描述】:根据文档(),它说:
当一个实现引入一个类的临时对象时 有一个非平凡的构造函数([class.default.ctor], [class.copy.ctor]),它应确保调用构造函数 临时对象。同样,应调用析构函数 具有非平凡析构函数([class.dtor])的临时。暂时的 对象被销毁作为评估的最后一步 (词法上)包含的完整表达式([intro.execution]) 它们被创建的地方。这是真的,即使那个评价 以抛出异常结束。价值计算和副作用 销毁临时对象仅与 全表达式,没有任何特定的子表达式。
如何理解“临时对象被销毁作为评估完整表达式([intro.execution])的最后一步,该完整表达式(在词法上)包含它们被创建的点。”?任何人都可以说清楚通过一些简单的例子?
【问题讨论】:
有关文档中技术含量较低的解释,请参阅A: Life span of temporary arguments?。 (我终于想到要搜索“完整表达”而不是“临时销毁”。) 你真好。我现在就去读。 我已经阅读了上述文档,又提出了一个问题。"Class CTest; CTest fool(CTest); CTest cTes = func(CTest());
" 我认为临时对象(fool(CTest())
中的CTest()
)应该在评估整个表达式(@ 987654325@) 和 在评估了复制构造函数之后 (CTest cTes=
)。我说的对吗?谢谢。
您进入了术语变得奇怪的地方之一。从技术上讲,CTest cTes = func(CTest());
不是“表达”,而是“完整表达”,就像听起来一样疯狂。所以,是的,临时文件在复制构建后被销毁。
@JaMiT 太棒了!“表达”和“完全表达”有什么区别?
【参考方案1】:
简单的例子。这个表达式产生一个临时对象:
std::string("test")
这里,该表达式被用作子表达式:
function(std::string("test"));
// point A
在点 A,临时对象已被销毁,因为该点位于创建临时对象的完整表达式之后。
下面是一个例子,如果不理解这条规则,如何编写一个错误:
const std::string& function(const std::string& arg)
return arg;
const std::string& ref = function("test");
std::cout << ref;
这里,作为参数创建的临时对象在完整表达式之后被销毁,因此ref
变得无效 - 一个悬空引用。将无效引用插入输出流时,行为未定义。
【讨论】:
谢谢你的澄清。你的意思是临时对象(std::string("test")
)在function
的返回后被销毁?我可以这样想吗。
@sunshilong369 是的。临时对象在整个函数中都处于活动状态,但在函数返回后就不再处于活动状态。【参考方案2】:
在许多情况下有效的解释是临时对象在执行到达语句末尾的分号时被销毁。此解释未涵盖某些语言结构(例如for
循环),因此不要太用力。有关异常的更好解释,请参阅Statement that isn't a full-expression。
举个例子:
i = foo1(foo2(std::string("test")));
临时字符串在赋值之后一直保持活动状态,因为赋值发生在语句结束之前。 (在这种情况下,完整的表达式就是语句。)
【讨论】:
感谢您的澄清。假设这是foo1(foo2((std::string("test"))));
的表达式,您的意思是临时对象(std::string("test")
)应该在返回之后被销毁函数foo1
?
@sunshilong369 是的。以上是关于如何理解“临时对象被销毁作为评估完整表达式的最后一步”?有人可以通过一些简单的例子说清楚吗?的主要内容,如果未能解决你的问题,请参考以下文章