了解 std::array 的移动语义

Understanding move semantics for std::array

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

#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';
}

我原以为 main 的 std::cout 会出现分割错误,因为 v_ 应该在 tryToMove 中移动。然而,输出是:

1 2 3
1 2 3

这里到底发生了什么?

谢谢!

I was expecting a sementation fault

首先,大多数导致段错误的方法都是未定义行为的结果,在这种情况下任何事情都可能发生,而你可能不应该期待任何具体的东西。

since v_ is supposed to be moved

A std::array 包含直接嵌入其中的元素(不是在堆上,由指针引用,就像 std::vector 那样)所以您不能将其内容移动到任何地方。他们将永远在里面。

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

问题是您期望一个分段错误只是因为您访问了不再属于您的内存。

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

在这种情况下,v 的状态是未指定的,因此您对它的三个元素的访问可能有效,也可能无效。当它们有效时(它们可能是因为在这种情况下可能会复制基础数据)你就没事了;当它们无效时,您不能简单地假设结果将是分段错误。 OS 必须具备一些条件才能引发分段错误:它不是检测错误的灵丹妙药。