提问人:Itachi Uchiwa 提问时间:8/15/2021 更新时间:8/16/2021 访问量:344
编译器如何复制作为数组的成员数据?
How does the compiler copy member data that are arrays?
问:
AFAIK,无法复制或分配数组,因此:
int a[5] = {1, 2};// 1 2 0 0 0
int b = a;// error
b = a; // error
但是编译器如何通过简单的 copy-ctor 和 copy-assignment 运算符复制作为类/结构类型成员数据的数组呢?
// trivial struct
struc Arr{
int arr_[7];
};
Arr a = {5, 7, 2, 10, 9, 1, 2};
Arr b = a;// trivial cpy-ctor
a = b; // trivial cpy-assignment operator
- 那么编译器是否执行类似以下操作: ?或者它遍历 的所有元素并将它们 cpy-assign 给它们在 中的对应元素?
this->arr_ = rhs.arr_
rhs.arr_
rhs
答:
所有数组和所有对象,都归结为内存中的位和字节。唯一的区别是哪些特定的位和字节,以及它们的解释和使用方式
所有位和字节都完全相同。没有特殊的人,也没有弱势的人。
复制这些位和字节是计算机所做的。编译器只需发出适当的指令,将适当的位和字节从连续内存的一部分复制到连续内存的另一部分。与等效循环非常相似,在数组中的每个值上,都可以复制它。C++ 标准不要求编译器以任何特定方式实现它的任何部分。C++ 标准定义了语言每个部分的效果和结果(以及所需的条件)。编译器如何做到这一点,完全由编译器决定。你不在乎它。这是编译器的责任。
C++ 编程语言的规则禁止以这种方式复制单个数组。为什么会这样,那将是一个不同的问题,但就这个问题而言,它只是禁止这样做的规则。
但它们确实允许默认构造函数和赋值运算符影响数组成员的复制/移动。
稍后,您的 C++ 教科书将向您介绍模板。您将学习如何像使用数组一样使用它。要分辨出其中的区别是非常非常困难的。它就像一个数组,正确编写的代码将像数组一样使用它。但它不是一个数组。因此,可以像复制和移动等效数组一样复制/移动它。std::array
评论
std::array
那么编译器是否执行类似以下操作: ?
this->arr_ = rhs.arr_
不。正如你所说,这不会编译。
或者它遍历 的所有元素并将它们复制分配给它们在 ?
rhs.arr_
lhs
对于复制分配运算符 - 是。
对于复制构造函数 - 否。在那里,每个元素都是从另一个数组的相应元素复制构造的(而不是赋值的)。喜欢这个:
Arr(const Arr &other) : arr_{other.arr_[0], other.arr_[1], ..., other.arr_[6]} {}
手动编写的循环是不可能做到的。如果要手动执行,则需要手动拼写每个元素。
但是,当然,如果复制构造函数和复制赋值都是微不足道的(这意味着它们有效地逐字节复制结构,而不做任何其他事情),那么复制构造函数是复制构造每个元素还是复制赋值它并不重要,因为两者都做同样的事情。
Note that being trivial is unrelated to being compiler-generated. The question gave me a feel that there might some confusion here.
评论
arr_{other.arr_[0], other.arr_[1], ..., other.arr_[6]}
std::array
: arr_(other.arr_)
int
评论
is_standard_layout
is_trivial
memcpy