Хорошо ли определен адрес члена неинициализированного объекта?

Рассмотрим следующий пример. когда 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; кажется в порядке) но я не могу найти документацию, подтверждающую это тоже.

5

Решение

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

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

От [Basic.life]

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

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

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

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

4

Другие решения

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

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

2

По вопросам рекламы [email protected]