在C++中将通过引用传递的值赋给成员变量

3
我希望你能帮我翻译关于C++作用域的内容。请看下面的例子:
class C
{
    int i_;
public:
    C() { i_ = 0;}
    C(int i) { i_ = i; }
    C(const C &c) {
        i_ = c.i_;
        cout << "C is being copied: " << i_ << endl;
    }
    int getI() { return i_; }
    ~C() {cout << "dstr: " << i_ << endl;}
};

class D
{
    C c_;
public:
    void setC(C &c) { c_ = c; }
    int getC_I() { return c_.getI(); }
};

void Test(D &d)
{
    C c(1);
    d.setC(c);
    //here c is going out of scope, surely it will be destroyed now?
}

int main()
{
    D d;
    Test(d); //this sets value of c_ to the local variable in Test. 
             //Surely this will be invalid when Test returns?
    int ii = d.getC_I();
    cout << ii << endl;
}

运行此程序将输出:
dstr:1 1 dstr:1
显然,第一个析构函数调用发生在Test中,另一个则是当程序终止并销毁d时发生的。
所以我的问题是:c被复制到哪里了?我的推理有错吗?我想问的一般性问题是:拥有一个接受对象引用并将其存储在成员变量中的成员函数是否安全?
非常感谢您的帮助。
3个回答

2
当你执行c_ = c; Where was c copied?时,你正在调用c_operator=,它将把c的内容复制到c_
如果c_也是引用,则不会复制任何内容,并且程序会导致像你预期的错误。

2

这里正在复制C语言:

void setC(C &c) { c_ = c; }

如果你想存储一个引用,那么你的成员变量c_也应该是一个引用。如果你存储一个引用,那么你需要注意传入变量的生命周期。


@Charles 标准规定:“类对象可以通过两种方式进行复制,即通过初始化[...]和赋值(5.17)。从概念上讲,这两个操作由复制构造函数(12.1)和复制赋值运算符(13.5.3)实现。” - Johannes Schaub - litb
@litb:说得对,我撤回我原来的评论和答案。 - CB Bailey

2

您的代码目前看起来很好。 D::c_ 的类型是 C 而不是 C &。 您的 SetC 接受一个 C 的引用,并将该引用所引用的值赋给 C::c_,因此您拥有了一个完全独立的具有相同值的 C 对象。由于您在 main 中使用自动存储期创建了 d 和其中的 c_,因此它们将一直有效,直到您从 main 退出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接