Присвоение значения, переданного по ссылке на переменную-член (в C ++) - PullRequest
3 голосов
/ 26 июня 2010

Я пытаюсь обернуть голову о области видимости в 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;
}

Запуск этой программы выводит:

ДСТР: 1
1
дстр: 1

По-видимому, первый вызов деструктора происходит в Test, а другой - когда программа завершается и d уничтожается.

Итак, мой вопрос: где был скопирован c? Есть ли вина в моих рассуждениях? И общий вопрос, который я пытаюсь спросить: безопасно ли иметь функцию-член, которая получает ссылку на объект и затем сохраняет ее в переменной-члене?

Большое спасибо за вашу помощь.

Ответы [ 3 ]

2 голосов
/ 26 июня 2010

C копируется сюда:

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

Если вы хотите сохранить ссылку , тогда ваша переменная-член c_ также должна быть ссылкой.Если вы храните ссылку, вам нужно быть осторожным с временем жизни переменной, которую вы передаете.

2 голосов
/ 26 июня 2010

Ваш код в порядке, как сейчас.D::c_ имеет тип C, а не C &.Ваш SetC берет ссылку на C и присваивает значение, на которое ссылается эта ссылка, C::c_, так что у вас есть совершенно отдельный объект C, имеющий то же значение.Поскольку вы создали d с автоматической продолжительностью хранения в main, оно и c_, являющееся его частью, остаются действительными до тех пор, пока вы не выйдете из main.

2 голосов
/ 26 июня 2010

Где был скопирован c?

Когда вы делаете c_ = c;Where was c copied?, вы звоните operator= на c_, что скопирует содержимое c в c_.

Если бы c_ было также ссылкой, ничего не было бы скопировано, и программа вызвала бы ошибку, как вы ожидаете.

...