2013-08-14 3 views
3

Это простой вопрос, но я не могу управлять, чтобы найти его на Google:Переместить конструктор для типа указателя?

Есть специальный ход конструктор для интегрального типа (включая указатели)

Например, если я делаю:

int* a = new int(2); 
int* b = std::move(a); 

Гарантированное ли оно указание на NULL? Как насчет, если a и b были int?

+1

Ваш язык означает, что вы ожидаете, что 'a' будет NULL, если у него есть специальный конструктор перемещения. Зачем? Перемещение конструкторов для нормальных классов также не делает такой гарантии. –

+0

@Benjamin Lindley Я думал, что, возможно, a будет установлен в NULL, поэтому, если мне когда-нибудь понадобится удалить указатель, это не будет иметь никакого эффекта (поскольку значение, которое было перенесено) – lezebulon

+0

Конструктор перемещения просто должен покинуть RHS в состоянии, в котором можно либо уничтожить (то есть выйти из сферы действия), либо переназначить (или какую-либо другую операцию без предварительных условий). И это всегда безопасные операции для таких основных типов, как указатели. –

ответ

12

гарантированно указывает на NULL?

Нет, это не изменится. Инициализация встроенных типов никогда не будет изменять инициализатор. Могут изменить только инициализацию типа класса с помощью конструктора перемещения (или злого неконстантного конструктора копирования, такого как auto_ptr).

Например, если вы использовали std::unique_ptr, а не тупые указатели, тогда a будет пуст после инициализации b.

Как насчет того, были ли a и b ints?

По-прежнему нет.

+0

Это верно на практике, но запрещает ли это стандарту делать равным нулю после перемещения? Например, это может быть полезно для целей отладки. – jcoder

+2

@jcoder: Да, стандарт запрещает это. Инициализация объекта, не относящегося к типу класса (описанного в C++ 11 8.5/16, final bullet), не включает ничего, что может изменить выражение инициализатора. Он просто оценивает выражение и при необходимости применяет стандартные преобразования. Если вы хотите, чтобы указатели были умными, вам нужно использовать классы интеллектуальных указателей. –

+0

спасибо за ссылку :) – jcoder

0

Обратите внимание, что в стандартном перемещении библиотеки подразумевается, что перемещенный объект остается в допустимом, но неуказанном состоянии. Это означает, что после такой операции значение перемещенного объекта должно быть уничтожено только или назначено новое значение; доступ к нему в противном случае получается неопределенное значение

Цитируется - http://www.cplusplus.com/reference/utility/move/

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

+2

Значение 'a' задается языком. Это назначение не изменяется. –

+7

Этот ответ неправильный. Цитата не имеет ничего общего с инициализацией встроенных типов из ссылок rvalue, о чем и идет речь. «Перемещение» происходит только при вызове функции (как правило, оператор конструктора/назначения) с ссылкой на rvalue, а указатели не имеют конструкторов перемещения. 'std :: move' сам ничего не двигает; он просто дает вам ссылку, с которой можно перемещаться. –

+0

@MikeSeymour Nice, спасибо за исправление – dchhetri

1

Простой ответ, необработанный указатель не является умным указателем, поэтому нет, перемещение по простым типам не очистит перемещение от значения или, по крайней мере, не гарантирует этого. Почему нужно перемещать указатель на исходный указатель, перемещенный из значения в nullptr? У него нет понятия delete или что двойной delete может быть чем-то злым или нежелательным. Перемещение просто гарантирует, что объект останется в действительном, но неуказанном состоянии и сделать перемещение простых типов более сложными и неэффективными, чем копирование, безусловно, будет противоречить друг другу. Любая семантика выше «Хранить адрес для меня» - это специальные типы интеллектуальных указателей и возможность повторного использования простого необработанного указателя.

Смежные вопросы