Понимание времени жизни объекта, области видимости, RAII - PullRequest
2 голосов
/ 20 марта 2011

В коде ниже , когда я передаю неназванную переменную A в ctor B, переменная уничтожается после строки. Согласно этот ответ :

Временные объекты уничтожаются на конец полного выражения они часть. Полное выражение является выражение, которое не является подвыражением какого-то другого выражения. Обычно это означает, что он заканчивается на ; (or ) for if, while, switch etc.), обозначающем конец заявления.

Я понял, но как класс B может узнать значение своей переменной mamber_a после ее разрушения? Я знаю, что экземпляр ctor A называется enver. Как это возможно?

#include <iostream>
using namespace std;

class A 
{
        int sign;
        A();
        const A & operator=(const A &);
public:
        A(int x) : sign(x) { 
                cout << "A ctor : " << sign << endl; 
        }

        void WriteA() const { 
                cout << sign << endl; 
        }

        ~A() { 
                cout << "A dtor : " << sign << endl; 
        }

        A(const A &) {
                cout << "A copied : " << sign << endl;
        }
};

class B
{
        int sign;
        const A & member_a;
public:
        B(const A & aa , int ww ) : sign (ww) ,member_a(aa) { 
                cout << "B ctor : " << sign << endl; 
        }

        void WriteB() const {
                cout << "Value of member_a :";
                member_a.WriteA();      
        } 

        ~B() { 
                cout << "B dtor : " << sign  << endl;
        }
};

int main() {
        A a(10);
        B b1(a,1);
        b1.WriteB();     

        B b2(A(20),2);
        b2.WriteB();

        return 0;
}

Вывод:

A ctor : 10
B ctor : 1
Value of member_a :10
A ctor : 20
B ctor : 2
A dtor : 20
Value of member_a :20 // Object A was destructed. Where does this 20 come from?
B dtor : 2
B dtor : 1
A dtor : 10

Ответы [ 2 ]

5 голосов
/ 20 марта 2011

У вас есть одна из сложных частей C ++

Вполне вероятно, что member_a имеет значение 20. Вы попадаете в то, что называется неопределенным поведением.

Когда класс сохраняет ссылку на внешний объект, программист обязан убедиться, что время жизни объекта длится дольше, чем указанный объект. В этом случае, когда вы вызываете member_a.WriteA();, объект уже был уничтожен, и, таким образом, вы получаете доступ к памяти, которая потенциально может вам не принадлежать (в этом случае это просто происходит в месте поблизости, которое не было переопределено (полностью шанс)).

Если вы собираетесь сохранить ссылку на объект. Вы можете сохранить ссылку на const, но иногда лучше сделать параметр нормальной ссылкой, чтобы вы не могли случайно передать временное значение (это не всегда работает, так как вам может потребоваться передать объект const по ссылке).

1 голос
/ 20 марта 2011

Использование ссылки на разрушенный объект является «неопределенным поведением».

В деструкторе А, попробуйте установить «знак» на «-1» и посмотреть, что произойдет. Вероятность того, что вызов «WriteB» покажет, что вы отправили сообщение умершему объекту.

Теперь попробуйте поместить связку стека с помощью кода между конструктором b2 и вызовом b2.WriteB, например, вызовом подпрограммы. Теперь вы, вероятно, обнаружите, что вызов печатает что-то другое.

...