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

C++未赋值接收函数返回值时临时对象构造能否被优化消除

C++中未接收函数返回值时,构造函数的副作用能否被编译器优化消除

在如下示例中:

struct Foo
{
     Foo() { std::cout << "Foo constructor called\n"; }
};

Foo getFoo()
{
     return Foo();
}

int main()
{
     Foo foo = getFoo();
}

由于复制消除(copy elision)机制的存在,我们无法确定构造函数会被调用一次还是两次:

复制消除是C14标准前唯一允许改变程序可观测副作用的优化形式;自C14起,它与分配消除及扩展(allocation elision and extension)并列为两种允许改变可观测副作用的优化形式。

因此这类场景下程序的副作用执行结果是无法被依赖的。如果返回值被赋值接收,我们可以确定拷贝构造函数至少会被调用一次。但如果调用getFoo()时(甚至是意外误调用)没有赋值接收返回值,编译器是否可以完全不构造对应的对象?实际开发中遇到过如下侵入式智能指针的实现场景,就涉及这个问题:

template <typename T>
struct IntrusivePointer
{
    IntrusivePointer(T* ptr) : ptr(ptr) { if (ptr) ptr->increment_ref_count(); }
    T* ptr = nullptr;

    ~IntrusivePointer() { if (ptr) ptr->decrement_ref_count(); }
};


class Thing {
public:
    int ref_count = 0;
    void increment_ref_count() { ++ref_count; }
    void decrement_ref_count()
    {
        --ref_count;
        if (ref_count == 0)
        {
             recycle();
        }
    }

    void recycle();
};

struct Manager
{
    static inline std::vector<Thing*> availableThings;
    static inline int num_things_used = 0;

    /* 如果这个函数被调用但返回值没有被接收,整个引用计数系统会不会崩溃? */
    IntrusivePointer<Thing> getThing()
    {
        Thing* thing = availableThings.back();
        availableThings.pop_back();

        ++num_things_used;

        /* 就算返回值没被接收,按逻辑下面的临时对象也应该被构造:
        - 只要有任意一个IntrusivePointer对象被构造,最终引用计数归零后对象就会被回收
        - 但我不确定这个对象的构造过程会不会被编译器完全优化掉 */
        return IntrusivePointer<Thing>(thing);
    }

    static void recycle(Thing* thing) { 
        availableThings.push_back(thing); 
        --num_things_used;
    }
};


inline void Thing::recycle()
{
    Manager::recycle(this);
}

针对这个场景的结论如下:

  • 如果返回值没有被赋值接收,严格来说不存在复制消除的适用场景,任何消除IntrusivePointer构造副作用的优化都不属于复制消除的合法覆盖范围。
  • 编译器确实可能检测到返回值未被使用,从而尝试优化掉无关逻辑,但只要对象构造存在可观测的副作用,且不符合复制消除或分配消除与扩展的适用条件,编译器无权消除构造函数产生的副作用,上述侵入式指针的引用计数增减、对象回收逻辑,不会因为返回值未被接收就被优化跳过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 01:18:30