После обсуждения мой ответ на этот вопрос, по-видимому:
следующий код разрешен
struct Foo {
int x;
};
Foo f;
Foo & f_ref = f;
(&f) -> ~Foo ();
new (&f) Foo ();
int x = f_ref .x;
но следующий код запрещен
struct Foo {
const int & x; // difference is const reference
Foo (int & i) : x(i) {}
};
int i;
Foo f (i);
Foo & f_ref = f;
(&f) -> ~Foo ();
new (&f) Foo (i);
int x = f_ref .x;
Из-за 3,8 долл. США / 7
Если после того, как время жизни объекта закончилось и до того, как хранилище, которое занимал объект, будет повторно использовано или освобождено, новый объект создается в том месте хранения, которое занимал исходный объект, указатель, указывающий на исходный объект, ссылка, которая ссылается на исходный объект, или имя исходного объекта будет автоматически ссылаться на новый объект и, как только время жизни нового объекта начнется, может использоваться для управления новым объектом, если:
- тип исходного объекта не квалифицируется как константа, и, если тип класса, не содержит каких-либо нестатических членов данных, чей тип квалифицируется как константа, или ссылочный тип ...
Я могу понять, как ссылка на f.x
может быть признана недействительной, когда f перестает существовать, но я не понимаю, почему f_ref
следует признать недействительным только потому, что один из его членов является константой и / или ссылкой, а не иначе: это была ссылка на Foo
до и является ссылкой на Foo
после.
Может кто-нибудь объяснить причину этого условия?
Редактировать
Спасибо за ответы. Я не покупаю аргумент «гарантия, что он не изменится», потому что в настоящее время мы не разрешаем оптимизаторам кэшировать референции, например:
struct Foo {
const int & x;
Foo (const int & i) : x(i) {}
void do_it ();
};
int i;
Foo f (i);
const int & ii = f.x;
f .do_it (); // may modify i
std :: cout << ii; // May NOT use cached i
Я не понимаю, как do_it
разрешено аннулировать ссылочные значения, но operator new
нет - Точки последовательности делают кешированные значения недействительными: почему следует исключить удаление / новое размещение?
do_it
мог изменитьi
? - person UncleBens   schedule 28.09.2011const_cast<int &>(x) = 1;
вdo_it
совершенно нормально, учитывая, что референдумx
на самом деле является изменяемым объектомint
. Если это то, что делаетdo_it
, тогда было бы ошибкой (UB) делатьconst int i; Foo f(i); f.do_it();
, но с неконстантнымиi
все в порядке. - person Steve Jessop   schedule 28.09.2011