理解std :: array的移动语义

时间:2015-03-11 14:05:59

标签: c++ c++11 move-semantics

我试图理解移动语义,所以我做了以下测试:

#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

这里到底发生了什么?

谢谢!

2 个答案:

答案 0 :(得分:14)

  

我原本期待一个癫痫发作错误

首先,大多数获取段错误的方法是由于未定义的行为,在这种情况下,任何都可能发生,您可能不应该期待任何事情具体

  

因为v_应该被移动

std::array包含直接嵌入其中的元素(不在堆上,由指针引用,如std::vector所示),因此您无法将其内容移动到任何位置。他们永远都在里面。

所以你所做的就是从旧的数组初始化一个新数组,你没有移动任何东西。新数组的元素将由rvalue双精度初始化,但这也不会移动任何东西,因为你不能“移动”一个double(它没有外部分配的数据来传输)。所以它只是每个元素的副本。

答案 1 :(得分:1)

问题在于,您只是因为访问了不再属于您的内存而预期分段错误。

未定义的行为意味着任何事情都可能发生。

在这种情况下,v的状态未指定,因此您对其中三个元素的访问可能是有效的,也可能不是。当它们有效时(可能是因为在这种情况下可能会复制基础数据)你很好;当它们无效时,您不能简单地假设结果将是分段错误。操作系统需要做一些事情来提出分段错误:它不是检测错误的灵丹妙药。