2016-12-25 4 views
0

Моя проблема в том, что константа копирования по умолчанию. испортил мои указатели.Вставка элемента в контейнер: копировать конструктор беспорядок вверх указатели

Упрощенная версия:

  • У меня есть A класса с по умолчанию копию конструка.

  • A имеет 2 участника-участника: B и C.

  • B имеет указатель на C.

Ситуация:

  • хранить A в std::vector: vector.emplace_back(A(...));

  • emplace_back делает это:

    • Создание A (настройка указателя B на C и т.д.)

    • Копирование А в векторе. (по умолчанию копия СУУ: копии по стоимости)

    • Уничтожение "по происхождению" А.

. Результат:

  • Хранилище имеет A, который имеет B, который имеет указатель на старого в C. Что больше не существует.

Простое решение будет:

  • В A было бы указатели на B и C

Но это не так хорошо, потому что почему должны иметь указатели, когда его владеет его B и C и B и C ресурсом жизни с A.

Вопрос:

  • не лучший способ, чем иметь указатели в?

  • Или нет более простого способа, чем возиться с реализациями конструктора копирования?

  • Я думал, что emplace построит «на месте», так зачем нужна копия ctr?

+3

Я не понимаю, в чем вопрос. Возможно, вы предоставили бы соответствующий примерный код, чтобы узнать, что на самом деле происходит ... На основе вашего описания кажется, что 'C' должен иметь конструктор, принимающий адрес соответствующего объекта' B', а 'A' ​​должен иметь подходящий конструктор копирования/copy, чтобы правильно установить указатели на содержащийся объект 'C'. –

+0

Я удалил свой ответ, потому что это был намек на создание объекта * на месте *, но не затрагивает основную проблему испортения указателей. Для получения полного решения вам необходимо разместить образец кода или MCVE. –

+0

Emplace может вызывать перераспределение, которое копирует или перемещает элементы вокруг – MikeMB

ответ

1

нет лучшего способа, чем иметь указатели в?

Да, есть. Кроме того, я не вижу, как проблема с указателями в A.

Решение состоит в том, чтобы написать определенный пользователем конструктор копирования для A, который будет обновлять указатель скопированного элемента.

Или нет более простого способа, чем возиться с реализациями конструктора экземпляра?

Нет, конструктор копирования (возможно, возможно?) - самый простой способ обновить указатель на член элемента.

Я думал, что устанавливать конструкции "в месте"

Это делает.

так зачем нужна копия ctr?

Этого не происходит вообще.

В этом случае требуется либо механизм перемещения, либо копия, потому что вы передаете ему временный объект. Объект в векторе строится «на месте», используя конструкцию move (или copy, if not movable) с временным аргументом.

Вместо этого вы могли бы передать аргументы конструктора A direclty в emplace_back, чтобы не было задействовано никаких временных ограничений.

Обратите внимание, что создание объекта на месте не предотвращает копирование элемента вектора, если только вы не предварительно зарезервировали память, чтобы не происходило перераспределение.

0

Вы можете вручную написать конструктор копирования A, чтобы сделать правильную вещь.

Другой план, если все стандартное расположение, заключается в использовании указателей смещения. Указатель смещения сохраняет разницу в адресе между самим указателем и тем, на что он указывает. Обычно он использует max (ptrdiff_t) для null.

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

Однако, возможно, лучший план состоит в том, чтобы увеличить все методы в B, чтобы взять указатель-на-C и передать его каждый раз вместо хранения избыточного состояния.

Многое из того, что определяет правильный ответ из вышеизложенного, имеет значение AB и C, и насколько они независимы.