微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

按位复制和浅复制有什么区别吗?

如何解决按位复制和浅复制有什么区别吗?

关于问题 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 复制位时,填充位也将被复制。通过比较成员 xb,您无法分辨出区别,但是在位的级别上是有区别的。当您按位(而不是按成员)比较两个对象时,您会注意到这一点。


正如 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= 执行成员明智的复制。由于对象包含不用于成员的字节,因此您可以在复制成员并查看位表示后观察 ab 之间的差异。

另一方面,如果通过 memcpy 进行复制,那么 ab 的位表示将保证相同(即没有输出 !!! ).

,

如果我理解正确,按位复制是浅复制。按位复制只是简单地复制每一位以创建一个副本,而浅复制则更一般地复制您引用中所说的直接成员。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。