Я пытаюсь понять семантику перемещения, поэтому выполнил следующий тест:
#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
Что именно здесь происходит?
Спасибо!
2 ответа
Я ожидал ошибки сегментации
Прежде всего, большинство способов получить segfault - это результат неопределенного поведения, и в этом случае может произойти что угодно , и вам, вероятно, не следует ожидать чего-либо конкретного.
поскольку предполагается, что
v_
будет перемещен
std::array
содержит элементы, встроенные непосредственно в него (не в куче, на которую указывает указатель, как std::vector
), поэтому вы не можете никуда перемещать его содержимое. Они всегда будут внутри него.
Итак, все, что вы сделали, это инициализировали новый массив из старого, вы ничего не переместили. Элементы нового массива будут инициализированы двойниками rvalue, но это тоже ничего не перемещает, потому что вы не можете «переместить» двойник (у него также нет данных, выделенных извне для передачи). Так что это просто копия каждого элемента.
Проблема в том, что вы ожидали ошибки сегментации только потому, что получили доступ к памяти, которая вам больше не принадлежит.
Неопределенное поведение означает, что все может случиться.
В этом случае состояние v
не определено, поэтому ваши обращения к трем его элементам могут быть действительными, а могут и не быть. Когда они действительны (а они, вероятно, таковы, потому что в этом случае, вероятно, будут скопированы базовые данные), все в порядке; когда они недействительны, вы не можете просто предположить, что результатом будет ошибка сегментации. Чтобы операционная система могла вызвать ошибку сегментации, необходимо выполнить несколько действий: это не волшебная палочка для обнаружения ошибок.
Похожие вопросы
Связанные вопросы
Новые вопросы
c++
C ++ - это язык программирования общего назначения. Первоначально он был разработан как расширение C и имеет аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде (который должен быть) скомпилирован с помощью компилятора C ++. Используйте тег для конкретной версии для вопросов, связанных с конкретной версией стандарта [C ++ 11], [C ++ 14], [C ++ 17], [C ++ 20] или [C ++ 23] и т. Д. .