Какой член профсоюза становится активным после размещения нового - PullRequest
0 голосов
/ 17 января 2019

Относительно этого кода:

#include <string>

int main()
{
    union u {
        u() { i = 0; }
        ~u() {}

        int i;
        std::string s1;
        std::string s2;
    } u;

    new (&u) std::string{};
}

[intro.object] / 2 говорит, что

Объекты могут содержать другие объекты, называемые подобъектами. Субобъект может быть подобъектом-членом ([class.mem]), подобъектом базового класса ([class.derived]) или элементом массива. Объект, который не является подобъектом любого другого объекта, называется законченным объектом. Если объект создается в хранилище, связанном с подобъектом-членом или элементом массива e (который может или не может быть в пределах его времени жизни), созданный объект является подобъектом содержащего объект e, если:
- время жизни объекта, содержащего е, началось, а не закончилось, и
- хранилище для нового объекта точно перекрывает место хранения, связанное с e, и
- новый объект того же типа, что и e
(игнорируя квалификацию cv).

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

«Не требуется , как объект создается», среди прочего, означает, что указатель, данный для размещения new, не должен указывать на подобъект. Главным образом потому, что не может быть объекта, на который можно указать (обратите внимание, что [intro.object] / 2 не требует, чтобы подобъект был живым). В списке рассылки std-Discussion было задано, что для объекта x типа struct A { unsigned char buf[1]; }; существует ли разница между new (&x) A{} и new (x.buf) A{}? И ответ был отрицательным, в обоих случаях x.buf обеспечил бы хранилище для A{}. Потому что

Формулировки в [intro.object] и [basic.life] касаются адреса хранения, представленного указателем, а не объекта, на который он указывает.


[class.union] / 1 клянется, что «Максимум один из нестатических данных-членов объекта типа объединения может быть активным в любое время».

Какой из них стал активным в приведенном выше коде, s1 или s2?

1 Ответ

0 голосов
/ 17 января 2019

Указатель - это адрес, но для объектной модели это больше, чем адрес. Он указывает на конкретный объект по этому адресу. Несколько объектов могут существовать по определенному адресу, но это не означает, что указатели на любой из этих объектов являются одновременно указателями на другие объекты по этому адресу. Посмотрите, что [expr.unary.op] / 1 говорит об косвенности указателя:

результатом является lvalue, ссылающееся на объект или функцию, на которые указывает выражение.

Не "объекту по этому адресу"; это lvalue, относящееся к объекту , на который указывает. Очевидно, что в объектной модели C ++ несколько объектов могут существовать по одному и тому же адресу, но конкретный указатель на этот адрес не указывает на все эти объекты. Это указывает только на один из них.

[expr.unary.op] / 2 говорит: «Результатом унарного оператора & является указатель на его операнд». Следовательно, &u указывает на u, который имеет тип u (Кстати, действительно ли было необходимо называть объект так же, как тип?). &u не указывает на u.i, u.s1 или u.s2. Все они имеют тот же адрес, что и &u, но сам &u указывает только на u.

Таким образом, теперь возникает вопрос, что такое хранилище, представленное &u? Ну, согласно [intro.object] / 1, мы знаем, что «объект занимает область памяти». Если &u указывает на объект u, этот указатель должен поэтому представлять область памяти, занятую этим объектом. Не хранение любого из его подобъектов; это хранилище для этого объекта. В полном объеме.

Теперь мы доберемся до new(&u) std::string{}. Это выражение создает объект типа std::string{} в хранилище, представленном &u. Это означает повторное использование хранилища объекта u. Что в соответствии с [basic.life] / 1.4, заканчивает срок жизни u. Который заканчивает время жизни своего подобъекта активного члена.

Итак, ответ на ваш вопрос заключается в том, что ни один из них не становится активным, потому что объект u больше не существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...