关于What is the difference between memberwise copy, bitwise copy, shallow copy and deep copy?的问题,“第一个答案”的作者说:
浅拷贝
指仅复制对象的直接成员,而不复制对象所指向的任何结构。这是当你做一些明智的复制时得到的。
为什么我们要使用2术语与、按位复制和浅拷贝相同。他们之间真的没有区别吗?
也同样适用于其他语言(不仅仅是C++),我是否可以使用这些单词一般可以互换?
发布于 2020-12-27 11:01:46
一个稍微明智的拷贝是一个浅拷贝,但不一定相反。
原因是,由于填充,对象中可能会有您通常忽略的部分,但它们是对象的一部分。
举个例子
struct bar {
int x;
foo b;
};可以在记忆中像这样:
| x | some padding | b | more padding |当您通过memcpy复制比特时,填充位也会被复制。通过比较成员x和b,您无法分辨两者的区别,但在位的级别上是有区别的。您可以注意到,当您比较两个对象的位明智(而不是成员)。
正如在评论中指出的那样,填充并不是浅层复制与位复制不同的唯一原因。例如
struct foo{
foo* self;
foo() : self(this) {}
foo& operator=(const foo& other) {}
foo(const foo& other) : self(this) {}
};成员self应该指向对象本身,这是类的不变量(为了简单起见省略了适当的封装)。仅仅复制指针就会使self->this指向other而不是this,从而破坏不变量。operator=不需要复制任何东西,复制构造函数只需正确初始化self即可。这可以看作是一个浅拷贝,因为我们只是在“复制”指针self,而不是它所指向的指针(实际上,深拷贝在这里是致命的)。但是,按位复制会有所不同,它将在将a.self指向b后将b复制到a (这将再次破坏不变量)。
考虑一下这个例子:
#include <iostream>
#include <cstring>
struct X {
int a = 1;
double b = 2;
float c = 3;
X& operator=(const X& x){
a = x.a;
b = x.b;
c = x.c;
return *this;
}
};
int main()
{
X a;
X b;
std::cout << "sizeof(X) " << sizeof(X) << "\n";
std::cout << "sizeof(int) " << sizeof(int) << "\n";
std::cout << "sizeof(double) " << sizeof(double) << "\n";
std::cout << "sizeof(float) " << sizeof(float) << "\n";
//memcpy(&a,&b,sizeof(X));
a = b;
char* aptr = reinterpret_cast<char*>(&a);
char* bptr = reinterpret_cast<char*>(&b);
for (size_t i = 0; i < sizeof(X); ++i) {
if (aptr[i] != bptr[i]) std::cout << " !!! ";
}
}可能的产出是:
sizeof(X) 24
sizeof(int) 4
sizeof(double) 8
sizeof(float) 4
!!! X的大小不是其成员大小的总和。那是填充物。有关更多细节,请参考Struct padding in C++。
operator=做一个成员级拷贝。因为对象包含不用于成员的字节,所以在复制成员并查看位表示之后,可以观察到a和b之间的差异。
另一方面,如果复制是通过memcpy进行的,那么a和b的位表示将保证相同(即不输出!!!)。
发布于 2020-12-27 10:59:01
如果我正确理解,按位复制就是浅拷贝。按位复制只是在每一个位上复制以创建一个副本,而浅层副本在复制直接成员时则更为普遍,正如您在引用中所说的那样。
https://stackoverflow.com/questions/65465002
复制相似问题