了解 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 必须具备一些条件才能引发分段错误:它不是检测错误的灵丹妙药。
我试图理解移动语义,所以我做了以下测试:
#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 必须具备一些条件才能引发分段错误:它不是检测错误的灵丹妙药。