Я пытаюсь понять семантику перемещения, поэтому выполнил следующий тест:

#include <iostream>
#include <array>

using namespace std;

void tryToMove(array<double,3> && v) {
    array<double,3> v_ = std::move(v);
    std::cout << v_[0] << "  " << v_[1] << "  " << v_[2] <<'\n';
}

int main () {
    array<double,3> v{1,2,3};

    tryToMove(std::move(v));
    std::cout << v[0] << "  " << v[1] << "  " << v[2] <<'\n';
}

Я ожидал ошибки сегментации в std::cout главного сервера, поскольку v_ должен быть перемещен в tryToMove. Однако на выходе получается:

1 2 3
1 2 3

Что именно здесь происходит?

Спасибо!

4
Javi 11 Мар 2015 в 17:05

2 ответа

Лучший ответ

Я ожидал ошибки сегментации

Прежде всего, большинство способов получить segfault - это результат неопределенного поведения, и в этом случае может произойти что угодно , и вам, вероятно, не следует ожидать чего-либо конкретного.

поскольку предполагается, что v_ будет перемещен

std::array содержит элементы, встроенные непосредственно в него (не в куче, на которую указывает указатель, как std::vector), поэтому вы не можете никуда перемещать его содержимое. Они всегда будут внутри него.

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

16
Jonathan Wakely 11 Мар 2015 в 14:10

Проблема в том, что вы ожидали ошибки сегментации только потому, что получили доступ к памяти, которая вам больше не принадлежит.

Неопределенное поведение означает, что все может случиться.

В этом случае состояние v не определено, поэтому ваши обращения к трем его элементам могут быть действительными, а могут и не быть. Когда они действительны (а они, вероятно, таковы, потому что в этом случае, вероятно, будут скопированы базовые данные), все в порядке; когда они недействительны, вы не можете просто предположить, что результатом будет ошибка сегментации. Чтобы операционная система могла вызвать ошибку сегментации, необходимо выполнить несколько действий: это не волшебная палочка для обнаружения ошибок.

1
Lightness Races in Orbit 11 Мар 2015 в 14:10