赋值运算符 - 每个成员还是二进制副本?

时间:2014-04-18 21:11:51

标签: c++ copy variable-assignment binary-data

我想知道,只要所有包含的赋值都没有副作用,除了将二进制值传递给地址外,将源对象指针中的字节复制到目标而不是分配每个目标是不是更有效每个来源成员的成员?

作为一个子问题......我想知道读取模式如何影响内存控制器的负载。显然,当MC从正确对齐的地址读取其全宽时,它是最有效的。也许将所有成员合并到一系列最大宽数据类型以进行对齐会更有效,例如:如果MC是64位且成员数据集是10个字节,则复制64位和16位值,即使成员说是10 char s,因此以这种方式复制将使MC更好地饱和一次复制每个成员字符。

3 个答案:

答案 0 :(得分:6)

只要需要字节复制,只需让编译器为您生成默认值 如果效率最高,它还会使用memcpy自动优化它。

作为一个额外的好处,如果你添加一个具有更复杂(自包含)语义的成员,编译器仍然会做正确的事。

如果您添加一个不会在语义上复制其数据的成员,您只需自己进行操作。

答案 1 :(得分:0)

一般来说,memcpy总是比每个成员副本更快。一些警告:

  • memcpy通常会以这样的方式工作,即只要有可能就会进行对齐读/写。但是,这完全取决于平台,而memcpy在理论上可能非常低效

  • 如果结构没有对齐,那么每个成员的副本也需要不对齐的访问

  • 包装结构会变慢,除非它们也是对齐的(如SSE,NEON等)

  • 如果结构中有填充,memcpy将不可避免地复制更多的字节。

  • 确定答案的最佳方法是在目标计算机上构建并运行/配置它,同时记住不同的结构可能具有不同的特征。

答案 2 :(得分:0)

memcpy仅适用于POD类型。只要你有析构函数,构造函数,虚函数,私有数据,继承,memcpy对象都将是未定义的行为。因此,它适用于像

这样的类
class PODType {
public:
    int x;
    int y;
};

class Object {
public:
    PODType m;
    Object& operator=(Object const& x) {
        memcpy(&m, x.m, sizeof(PODType));
        return *this;
    }
};

但是现在,随着程序的发展,有人将PODType更改为具有自定义构造函数,因为它很方便,或者添加析构函数或执行使其成为非POD的其他内容。 memcpying它的所有类现在都有未定义的行为。在这些情况下,最好使用编译器生成的赋值运算符。

如果您担心表现,

  1. 不要过早优化
  2. 使用分析器和度量