Хорошо ли определен адрес члена неинициализированного объекта? - PullRequest
0 голосов
/ 25 апреля 2018

Рассмотрим следующий пример.Когда создается bar, он дает конструктору базового типа (foo) адрес my_member.y, где my_member - элемент данных, который еще не был инициализирован.

struct foo {
    foo(int * p_x) : x(p_x) {}
    int * x;
};

struct member {
    member(int p_y) : y(p_y) {}
    int y;
};

struct bar : foo
{
    bar() : foo(&my_member.y), my_member(42) {}
    member my_member;
};

#include <iostream>

int main()
{
    bar my_bar;
    std::cout << *my_bar.x;
}

Этохорошо определены?Законно ли брать адрес элемента данных неинициализированного объекта?Я нашел этот вопрос о передаче ссылки на неинициализированный объект, но это не совсем то же самое.В этом случае я использую оператор доступа к элементу . для неинициализированного объекта.

Это правда, что адрес элемента данных объекта не должен изменяться при инициализации,но это не обязательно делает взятие того адреса четко определенным.Кроме того, на странице ccpreference.com на операторах доступа к элементу есть следующее:

Первый операнд обоих операторов оценивается, даже если в этом нет необходимости (например, когда второйоперанд называет статический член).

Я понимаю, что это означает, что в случае &my_member.y my_member будет оцениваться, что я считаю хорошим (например, int x; x; кажется хорошим), ноЯ также не могу найти документацию, подтверждающую это.

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

Сначала давайте уточним вопрос.

То, что вы делаете, не использует неинициализированный объект, вы используете объект не в течение срока его службы.my_member создается после foo, поэтому время жизни my_member еще не началось в foo(&my_member.y).

С [basic.life]

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

  • glvalue используется для доступа к объекту, или [...]

Здесь доступ к нему означает специально дляпрочитайте или измените значение объекта.

Оценка my_member дает lvalue, и нет ничего, что требовало бы преобразования в prvalue, следовательно, оно остается lvalue.Аналогично, оценка my_member.y также является lvalue.Затем мы заключаем, что к значению объекта не обращались, это хорошо определено.

0 голосов
/ 25 апреля 2018

Да, вам разрешено передавать &my_member.y в конструктор foo и даже копировать указатель - что вы делаете с x(p_x).

Поведение разыменования этого указателя в конструкторе foo не определено. (Но ты этого не делаешь.)

...