Размещение новых брейков минусов и ссылок? - PullRequest
8 голосов
/ 28 сентября 2011

После обсуждения моего ответа на этот вопрос , по-видимому:

следующий код это разрешено

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

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

  • тип исходного объекта не является const-квалифицированным, и, если тип класса, не содержит никакого нестатического члена данных, тип которого является const-квалифицированным или ссылочным типом ...

Я могу понять, как ссылка на f.x может быть признана недействительной, когда f перестает существовать, но я не понимаю, почему f_ref следует сделать недействительной исключительно потому, что один из ее членов является const и / или ссылкой, а не иначе : это была ссылка на 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 нет - Точки последовательности делают недействительными кэшированные значения : почему исключение / location-new должно быть освобождено?

Ответы [ 4 ]

8 голосов
/ 28 сентября 2011

Я считаю, что мотивация - разрешить компилятору кэшировать значения const объектов (обратите внимание, что const objects , а не просто ссылки на указатели на const и ссылку на const),и адреса ссылок на ссылки между вызовами неизвестного кода.

Во втором примере компилятор может «увидеть», во-первых, что объект был создан и уничтожен, а во-вторых, что он был воссоздан с использованиемтакое же значение.Но авторы стандарта хотели, чтобы компиляторам было разрешено преобразовать этот код:

struct Foo {
    const int & x;
    Foo (int & i) : x(i) {}
};

int i = 1;
Foo f(i);

some_function_in_another_TU(&f);

std::cout << f.x;

В это:

struct Foo {
    const int & x;
    Foo (int & i) : x(i) {}
};

int i = 1;
Foo f(i);

some_function_in_another_TU(&f);

std::cout << i;           // this line is optimized

, поскольку ссылочный элемент f не может быть повторно установлен, иследовательно, должен по-прежнему относиться к i.Операция разрушится-и-конструкт нарушает не-reaseatable-ность опорного элемента x

1018 * Эта оптимизация не должна быть особенно спорным:. Рассмотрим следующий пример, используя const объекта, а необъект с const или ссылочным членом:
const int i = 1;
some_function_in_another_TU(&i);
std::cout << i;

Здесь i - это константа времени компиляции, some_function_in_another_TU не может правильно уничтожить ее и создать на ее месте другую int с другим значением,Таким образом, компилятору должно быть разрешено выдавать код для std::cout << 1; Идея состоит в том, что то же самое должно быть верно по аналогии для const-объектов других типов и для ссылок.

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

5 голосов
/ 28 сентября 2011

Насколько я могу судить, это всего лишь вопрос семантической корректности и соответствующих предположений, которые может сделать оптимизатор.Учтите это:

Bar important, relevant;

Foo x(important);  // binds as const-reference

Zoo z(x);  // also binds as const reference

do_stuff(z);

x.~Foo();
::new (&x) Foo(relevant);  // Ouch?

Объект z может разумно ожидать, что его ссылка на элемент Foo будет постоянной и, следовательно, будет ссылаться на important.Как гласит стандарт, уничтожение плюс новая конструкция в последних двух строках «автоматически обновляет все ссылки для ссылки на (логически) новый объект», поэтому теперь const-ссылка внутри z изменилась, несмотря на обещание быть постоянной.

Во избежание этого обратного удара в константность, вся реконструкция на месте запрещена.

2 голосов
/ 28 сентября 2011

Оптимизация. Предположим, у меня есть:

struct Foo
{
    int const x;
    Foo( int init ) : x( init ) {}
};

int
main()
{
    Foo a( 42 );
    std::cout << a.x << std::endl;
    new (&a) Foo( 3 );
    std::cout << a.x << std::endl;
    return 0;
}

Компилятор, увидев объект const int, имеет право предполагать, что значение не меняется; оптимизатор может просто сохранить значение в регистр через новое размещение и выведите его снова.

Обратите внимание, что ваш пример на самом деле совсем другой. Член данных имеет тип int const&; это ссылка (и ссылки всегда постоянны), поэтому компилятор может предположить, что ссылка всегда ссылается на один и тот же объект. (Значение этого объекта может измениться, если только сам объект также const.) Компилятор однако не может сделать такого предположения о стоимости объекта, на который он ссылается, поскольку i (в вашем случае) может явно измениться. Это факт, что ссылка само по себе (как и все ссылки) является неизменным, что вызывает неопределенное поведение здесь, а не const что вы написали.

0 голосов
/ 28 сентября 2011

Если что-то квалифицировано как const, вы не должны его изменять.Продление срока службы - это модификация с серьезными последствиями.(Например, подумайте, есть ли у деструктора побочные эффекты.)

...