You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于返回值临时对象销毁及复制消除新规则的技术问询

嗨,我来帮你理清这两个问题,结合你的代码逐一分析:

首先先把你的代码贴出来方便参考:

#include <iostream>
template <typename T> struct foo {
    T t;
    foo(const T& t) : t(t) {}
    ~foo() { std::cout << "destructor \n"; }
};
template <typename T> foo<T> make_foo(const T& t) {
    return {t};
}
问题一:返回值是否会产生会被销毁的临时对象?

答案是:在C++17及以后的标准下,不会产生额外的临时对象;C++17之前,编译器可以选择优化掉临时对象(大多数主流编译器都会这么做),但不是强制要求。

你的make_foo函数返回的是一个用列表初始化构造的foo<T>纯右值,在C++17的规则中,这种场景属于强制复制消除的范畴——编译器必须直接在调用方的目标内存位置(比如你用auto f = make_foo(...)定义的变量f的内存)构造这个foo<T>对象,不会生成中间临时对象,自然也就不会有额外的析构调用。

你可以自己做个测试:如果写auto f = make_foo(42);,程序只会在f生命周期结束时打印一次destructor,不会有额外的析构输出,这就证明没有临时对象被销毁。

问题二:复制消除的新规则是否适用于当前场景?

完全适用!

C++17对复制消除的规则做了强化,主要针对两种强制消除的场景:

  • 返回一个纯右值(比如你的代码里直接构造的foo<T>{t});
  • 返回一个与函数返回类型相同的命名局部对象(这是NRVO,不过C++17里NRVO依然是可选优化,不是强制的,但你的场景不属于这种)。

你的代码恰好命中了第一种强制消除的情况:return {t}本质是构造一个临时的foo<T>纯右值返回,C++17要求编译器直接把这个对象构造在调用方的目标位置,跳过临时对象的创建和销毁过程。

另外补充一点:你提到实际代码里t是lambda,这也不影响——模板参数推导会正确推导出lambda的类型,返回的foo<T>对象依然会被直接构造在调用方的变量中,不会产生临时对象。

内容的提问来源于stack exchange,提问作者463035818_is_not_an_ai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:56:42