按位复制和浅复制之间有什么区别吗?
Is any difference between bitwise copy and shallow copy?
关于问题 What is the difference between memberwise copy, bitwise copy, shallow copy and deep copy? 第一个答案的作者说:
Shallow Copy
Refers to copying just the immediate members of an object, without
duplicating whatever structures are pointed by them. It is what you
get when you do a bit-wise copy.
为什么我们有 2 个术语 用于与 按位复制 和 浅复制 相同的事情].真的没有区别吗?
是否同样适用于其他语言(不仅仅是 C++),我可以将这些词普遍互换使用吗?
如果我没理解错的话,按位拷贝就是浅拷贝。按位复制只是简单地复制每一位以创建一个副本,而浅表副本在复制直接成员时更为通用,如您的引述中所述。
按位复制是浅复制,但反之不一定。
原因是由于填充,对象中可能有您通常忽略的位,但它们是对象的一部分。
比如这个
struct bar {
int x;
foo b;
};
记忆中可以这样:
| x | some padding | b | more padding |
当您通过例如 memcpy
复制位时,填充位也将被复制。通过比较 x
和 b
成员,您无法分辨出差异,但在位级别上存在差异。当您按位(而不是按成员)比较两个对象时,您会注意到它。
正如 Yakk - Adam Nevraumont 在评论中指出的那样,填充并不是浅拷贝与按位拷贝不同的唯一原因。例如
struct foo{
foo* self;
foo() : self(this) {}
foo& operator=(const foo& other) {}
foo(const foo& other) : self(this) {}
};
成员 self
应该指向对象本身,这是 class 的不变量(为简单起见省略了适当的封装)。仅仅复制指针会使 self->this
指向 other
而不是 this
,因此打破了不变量。 operator=
不需要复制任何东西,复制构造函数只需要正确初始化 self
。这可以被认为是浅拷贝,因为我们只是在“复制”指针 self
而不是它指向的内容(实际上深拷贝在这里是致命的)。但是,按位复制会有所不同,它会在将 b
复制到 a
之后导致 a.self
指向 b
(这将再次破坏不变量)。
考虑这个例子:
#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
的位表示将保证相同(即没有输出 !!!
).
关于问题 What is the difference between memberwise copy, bitwise copy, shallow copy and deep copy? 第一个答案的作者说:
Shallow Copy
Refers to copying just the immediate members of an object, without duplicating whatever structures are pointed by them. It is what you get when you do a bit-wise copy.
为什么我们有 2 个术语 用于与 按位复制 和 浅复制 相同的事情].真的没有区别吗?
是否同样适用于其他语言(不仅仅是 C++),我可以将这些词普遍互换使用吗?
如果我没理解错的话,按位拷贝就是浅拷贝。按位复制只是简单地复制每一位以创建一个副本,而浅表副本在复制直接成员时更为通用,如您的引述中所述。
按位复制是浅复制,但反之不一定。
原因是由于填充,对象中可能有您通常忽略的位,但它们是对象的一部分。
比如这个
struct bar {
int x;
foo b;
};
记忆中可以这样:
| x | some padding | b | more padding |
当您通过例如 memcpy
复制位时,填充位也将被复制。通过比较 x
和 b
成员,您无法分辨出差异,但在位级别上存在差异。当您按位(而不是按成员)比较两个对象时,您会注意到它。
正如 Yakk - Adam Nevraumont 在评论中指出的那样,填充并不是浅拷贝与按位拷贝不同的唯一原因。例如
struct foo{
foo* self;
foo() : self(this) {}
foo& operator=(const foo& other) {}
foo(const foo& other) : self(this) {}
};
成员 self
应该指向对象本身,这是 class 的不变量(为简单起见省略了适当的封装)。仅仅复制指针会使 self->this
指向 other
而不是 this
,因此打破了不变量。 operator=
不需要复制任何东西,复制构造函数只需要正确初始化 self
。这可以被认为是浅拷贝,因为我们只是在“复制”指针 self
而不是它指向的内容(实际上深拷贝在这里是致命的)。但是,按位复制会有所不同,它会在将 b
复制到 a
之后导致 a.self
指向 b
(这将再次破坏不变量)。
考虑这个例子:
#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
的位表示将保证相同(即没有输出 !!!
).