Разрешено ли присваивать из объекта, который имеет некоторые неопределенные значения? - PullRequest
3 голосов
/ 02 июля 2019

Рассмотрим следующий класс, который может находиться либо в «непустом», либо в «пустом» состоянии, а в «пустом» состоянии другой элемент инициализируется по умолчанию (следовательно, имеет неопределенное значение):

struct MaybeInt {
  bool has_value;
  int value;

  MaybeInt()      : has_value(false) {}
  MaybeInt(int v) : has_value(true ), value(v) {}
};

Разрешено ли присваивать из построенного по умолчанию MaybeInt, например:

MaybeInt empty, another;
another = empty; // OK?

Как насчет строительства?

MaybeInt empty, another(empty); // OK?

Изменится ли ответ, если MaybeInt::value имеет тип char?

Ответы [ 2 ]

2 голосов
/ 02 июля 2019

another = empty действительно является UB, потому что empty.value имеет неопределенное значение и поскольку неявно определенный конструктор копирования класса копирует все элементы.

хитрость заключается в том, чтобы поместить члена value в союз.Таким образом, неявно определенный конструктор копирования объединения копирует представление объекта :

struct MaybeInt {
  bool has_value;
  union {
    int value;
    char _dumb;
    };

  MaybeInt()      : has_value(false) {}
  MaybeInt(int v) : has_value(true ), value(v) {}
  };

NB : это уловка низкого уровняиметь необязательный, который является тривиально копируемым.Это действительно важно для скорости выполнения кода.Этот класс может быть передан через вызов функции в регистре процессора, хотя это было бы невозможно, если бы его нельзя было легко скопировать.

0 голосов
/ 02 июля 2019

Ваш код приводит к неопределенному поведению.

MaybeInt empty, another;
another = empty; 

ОК.another имеет то же неопределенное значение, что и empty.Технически работает, что приводит к ошибкам на практике.

MaybeInt empty, another(empty);

empty содержит неопределенное значение, и оно копируется в another, который имеет то же значение, только теперь ваш класс считает это определено

Используйте std :: option , все, что должно быть необязательным, решается стандартным способом.(C ++ 17)

optional<int> x; // empty or not, you can use `value_or()` to get a default value.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...