Рассмотрим следующий код:
#include struct A { const char *name; A() : name("A") { std::cout << "A()\n"; } virtual ~A() { std::cout << "~A()\n"; } }; class B { const A& a; public: B() : a(A()) { }; void print_data() const { std::cout << a.name << '\n'; } ~B() { std::cout << "~B()\n"; } }; int main() { B b; b.print_data(); return 0; }
Выход из GCC 4.4:
A () ~ A () A ~ B ()
Мне это кажется странным. Я ожидал, что либо экземпляр временного экземпляра A будет привязан к B :: a, либо это временное само разрушается во время ~ B ().
В принципе, я думал, что B :: a всегда является действительной ссылкой в течение жизни b. Фактически b.print_data () работает, очевидно, и компилятор не дает никаких предупреждений.
Что говорит об этом стандартное c ++ 98/03?
Постоянные ссылки не продлевают срок жизни в classах, период. Это просто так. Они делают это только в Foo const& f = Foo();
где foo
возвращает значение, но это все.
§12.2 [class.temporary]
p4 Существует два контекста, в которых временные объекты уничтожаются в другой точке, чем конец полного выражения. […]
p5 Второй контекст – это когда ссылка привязана к временному. Временное, к которому привязана ссылка, или временный объект, являющийся полным объектом для подобъекта, связанного с временной привязкой, сохраняется для срока службы ссылки, за исключением случаев, указанных ниже. Временная привязка к ссылочному элементу в ctor-инициализаторе конструктора (12.6.2) сохраняется до тех пор, пока конструктор не выйдет .
Ваш код включает неопределенное поведение. Временное разрушается, когда конструктор B выходит (C ++ 03, [class.temporary]):
Временная привязка к ссылочному элементу в ctor-инициализаторе конструктора (12.6.2) сохраняется до тех пор, пока конструктор не выйдет.
Попробуйте изменить:
B() : a(A()) { cout << "B()\n"; };
Ты получишь:
A() B() ~A() A ~B()