【问题标题】:Can I safely memcpy a struct/class with copy constructor defined equivalently to the default copy constructor? [duplicate]我可以安全地 memcpy 一个与默认复制构造函数等效定义的复制构造函数的结构/类吗? [复制]
【发布时间】:2018-08-22 09:17:23
【问题描述】:

编辑: this 似乎完美地解决了我的问题。


关于Which type trait would indicate that type is memcpy assignable? (tuple, pair)

答案是std::is_trivially_copyable 可以告诉我我是否可以安全地memcpy 在我的对象周围。

现在考虑:

#include <iostream>
#include <type_traits>

struct A {
    int x;
    int y;
    A(const A& other) : x(other.x), y(other.y){}
};

struct B {
    int x;
    int y;
    B(const B& other) = default;
};

int main() 
{
    std::cout << std::boolalpha;
    std::cout << std::is_trivially_copyable<A>::value << '\n'; //false
    std::cout << std::is_trivially_copyable<B>::value << '\n'; //true
}

AB 在实际效果上都是相同的,但是 A 被检测为不可轻易复制。

那么,在memcpy-ing 这样的对象中,我会承担哪些风险?

用例:我想在 opencv 库中有一个cv::Point 的动态数组(不是vector,我会用realloc 使其增长),这可能是因为 C++98 兼容性不'不要使用default 来定义复制构造函数。

【问题讨论】:

  • 如果类型的复制构造函数确实只是复制字节,编译器无论如何都会知道将其优化为memcpy。不要出汗。
  • @Brian 查看编辑:我的精确用例是 cv::Point 的数组,我将在其中使用 realloc(我知道当 std::is_trivially_copyable 通过时,对 std::is_trivially_destructible 的检查变得多余)跨度>
  • 当默认的复制构造函数会这样做时,你为什么要 memcpy 对象?
  • @NeilButterworth 如果我想将cv::Point 的一个数组复制到另一个数组中(假设我有充分的理由不使用std::vector
  • @Antonio:我认为 Neil 的观点是 std::copy 将为您隐式调用默认的复制构造函数,那么为什么不直接这样做而不是测试定义行为的限制呢? std::copy(&amp;src[0], &amp;src[len], &amp;dst[0])std::copy_n(&amp;src[0], len, &amp;dst[0]) 在某种程度上比 memcpy(&amp;dst[0], &amp;src[0], len * sizeof(src[0])) 差吗?

标签: c++ opencv c++11 opencv3.0 memcpy


【解决方案1】:

主要风险是优化器彻底删除了对memcpy 的调用。这是一个完全合理的优化:最快的代码是没有被调用的代码,并且假设代码没有被错误的参数调用是安全的。

这也导致了第二个风险:优化器可能不仅会删除memcpy 调用,还会删除不可避免的所有代码。它可能会回溯到前面的if 语句,观察哪个分支指向memcpy,然后删除整个分支和测试条件。

【讨论】:

    【解决方案2】:

    编译器看到你有一个复制构造函数并退出。它不关心其中的内容,但如果编译器检测到分配没有向默认值添加任何内容的这种简单情况会很好。

    在这种特殊情况下,您可以侥幸逃脱,不会造成真正的伤害。
    另一方面,您给下一个开发人员留下了维护噩梦。
    你不能摆脱构造函数,或者用=default替换它吗?

    另外,我不确定 memcpy 是否会比这些简单构造函数调用的循环展开和内联链快得多?

    【讨论】:

      【解决方案3】:

      您可以根据需要来回存储对象。结构的二进制表示和对齐要求是相同的。

      如果你真的不相信,你可以创建 static_asserts 来检查大小和偏移量是否相同。

      【讨论】:

      • 这是不正确的
      • 在这个特定的例子中它有什么不正确的地方?
      • 该操作只是“未定义”,因为语言规则不解释构造函数正在做什么。但是现实中存在的任何实现都会很好。
      猜你喜欢
      • 2020-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-24
      • 2012-02-28
      相关资源
      最近更新 更多