我试图理解移动语义,所以我做了以下测试:
#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';
}
因为v_应该在std::cout
中移动,所以我期待主要tryToMove
中出现分段错误。但是,输出是:
1 2 3
1 2 3
这里到底发生了什么?
谢谢!
答案 0 :(得分:14)
我原本期待一个癫痫发作错误
首先,大多数获取段错误的方法是由于未定义的行为,在这种情况下,任何都可能发生,您可能不应该期待任何事情具体
因为
v_
应该被移动
std::array
包含直接嵌入其中的元素(不在堆上,由指针引用,如std::vector
所示),因此您无法将其内容移动到任何位置。他们永远都在里面。
所以你所做的就是从旧的数组初始化一个新数组,你没有移动任何东西。新数组的元素将由rvalue双精度初始化,但这也不会移动任何东西,因为你不能“移动”一个double(它没有外部分配的数据来传输)。所以它只是每个元素的副本。
答案 1 :(得分:1)
问题在于,您只是因为访问了不再属于您的内存而预期分段错误。
未定义的行为意味着任何事情都可能发生。
在这种情况下,v
的状态未指定,因此您对其中三个元素的访问可能是有效的,也可能不是。当它们有效时(可能是因为在这种情况下可能会复制基础数据)你很好;当它们无效时,您不能简单地假设结果将是分段错误。操作系统需要做一些事情来提出分段错误:它不是检测错误的灵丹妙药。