我可以安全地使用与默认复制构造函数等效定义的复制构造函数来构建结构/类吗?

时间:2018-03-13 23:44:56

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

编辑: 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这样的对象中接受哪种风险呢?

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

3 个答案:

答案 0 :(得分:0)

主要风险是优化器彻底删除了对memcpy的调用。这是一个非常合理的优化:最快的代码是未调用的代码,并且可以安全地假设代码未使用不正确的参数调用。

这也会带来第二个风险:优化器不仅可以删除memcpy调用,而且所有代码都不可避免地导致它。它可以回溯到前面的if语句,观察哪个分支通向memcpy,并且只删除整个分支和测试条件。

答案 1 :(得分:0)

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

在这种特殊情况下,你可以逃脱它,没有真正的伤害 另一方面,你为下一个开发者留下维护噩梦 你不能摆脱构造函数,或者用=default替换它吗?

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

答案 2 :(得分:-2)

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

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