如何解决按位复制和浅复制有什么区别吗?
关于问题 What is the difference between memberwise copy,bitwise copy,shallow copy and deep copy? first answer 的作者说:
浅拷贝
指只复制对象的直接成员,不复制 复制它们指向的任何结构。这就是你 进行逐位复制时获得。
为什么我们将 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
应该指向对象本身,这是类的不变量(为了简单起见,省略了适当的封装)。只是复制指针会使 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
的位表示将保证相同(即没有输出 !!!
).
如果我理解正确,按位复制是浅复制。按位复制只是简单地复制每一位以创建一个副本,而浅复制则更一般地复制您引用中所说的直接成员。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。