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

传递临时对象初始化引用成员变量的技术疑问

C++临时对象与构造函数相关疑问解答

代码示例

#include <iostream>
class B
{
public:
    B()
    {
        x = 5;
        std::cout << "B's default constructor called, creating object: " << this << "\n";
    }
    B(const B &other)
    {
        std::cout << "B's copy constructor called, copying other object: " << &other << "to this object: " << this << "\n";
    }
    B(B &&other)
    {
        std::cout << "B's Move constructor called, moving other object: " << &other << "to this object: " << this << "\n";
    }

    int x;
};
class A
{
public:
    A(B other_b) : b_(other_b)
    {
        std::cout << "A's constructor called, creating object: " << this << ", Address of b recieved is: " << &other_b << ", Address of A's b: " << &b_ << "\n";
    }
    void print()
    {
        std::cout << "Address of this object: " << this << ", Address of b: " << &b_ << "  " <<b_.x << std::endl;
    }

private:
    B &b_;
};

int main()
{
    A a{B()}; // initializing with temporary
    a.print();
}

编译输出

g++ -O0 -fno-elide-constructors ref_class_member.cpp  // to disable some comiler optimizations

B's default constructor called, creating object: 0x7ffebd667d5c
A's constructor called, creating object: 0x7ffebd667d50, Address of b recieved is: 0x7ffebd667d5c, Address of A's b: 0x7ffebd667d5c
Address of this object: 0x7ffebd667d50, Address of b: 0x7ffebd667d5c  5

技术疑问解答

问题1:当使用临时B对象调用A的构造函数后,该临时对象应已超出作用域被销毁,为何调用a.print()访问b_.x未出现错误?

这属于未定义行为,并非临时对象真的没被销毁。临时对象B()的生命周期在A的构造函数执行完毕后就已结束,对应的栈内存会被标记为可复用。只是此时这块内存还没有被后续操作覆盖,所以访问b_.x时刚好读取到了原来的有效值,但这种情况完全不可靠——只要后续有栈操作(比如其他函数调用)覆盖这块内存,就会触发崩溃或读取到错误值。

另外要注意:A的成员b_是引用类型,它绑定到了构造函数的参数other_b,而other_b是构造函数的局部变量,在构造函数结束后也会被销毁,所以b_本质上是一个悬垂引用,访问悬垂引用的任何成员都是标准明确规定的未定义行为。

问题2:A的构造函数为A(B other_b),按逻辑临时对象应被拷贝,为何未观察到copy constructor的调用?

这是因为C++17及以后引入的强制拷贝省略规则。当用纯右值(比如B()这种临时对象)初始化同类型对象时,编译器会直接在目标对象的内存位置构造这个临时对象,完全跳过拷贝或移动构造函数的调用。

即使你添加了-fno-elide-constructors编译选项,这个规则依然生效——因为这不是可选的编译器优化,而是C++标准强制要求的行为,编译器必须执行这种直接构造,因此不会触发拷贝或移动构造函数,自然看不到对应的打印输出。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 14:53:19