C++核心准则C.90:依靠构造函数和赋值运算符,而不是内存初始化和内存拷贝

C.90: Rely on constructors and assignment operators, not memset and memcpy

C.90:依靠构造函数和赋值运算符,而不是内存初始化和内存拷贝‍

Reason(原因)

The standard C++ mechanism to construct an instance of a type is to call its constructor. As specified in guideline C.41: a constructor should create a fully initialized object. No additional initialization, such as by memcpy, should be required. A type will provide a copy constructor and/or copy assignment operator to appropriately make a copy of the class, preserving the type's invariants.  Using memcpy to copy a non-trivially copyable type has undefined behavior.  Frequently this results in slicing, or data corruption.

标准C++机制通过调用构造函数构造某个类型的实例。正如C.41说明的:构造函数应该生成一个完全初始化的对象。不应该要求额外的初始化,例如使用memcpy。类型应该提供一个拷贝构造函数和/或者拷贝复制运算符以便适当地生成类的拷贝并维持类的不变量。使用memcpy拷贝一个非平常可拷贝类型的行为没有定义。通常会导致断层或者数据破坏。

Example, good(范例)

struct base
{
    virtual void update() = 0;
    std::shared_ptr<int> sp;
};

struct derived : public base
{
    void update() override {}
};

Example, bad(反面示例)

void init(derived& a)
{
    memset(&a, 0, sizeof(derived));
}

This is type-unsafe and overwrites the vtable.

这个函数类型不安全而且会覆盖虚函数表。

Example, bad(反面示例)‍

void copy(derived& a, derived& b)
{
    memcpy(&a, &b, sizeof(derived));
}

This is also type-unsafe and overwrites the vtable.

这个函数同样是类型不安全而且覆盖虚函数表。

Enforcement(实施建议)‍

  • Flag passing a non-trivially-copyable type to memset or memcpy.

  • 提示向memset或memcpy传递非平凡可拷贝类型的处理。

关于平凡拷贝请参见:

https://zh.cppreference.com/w/cpp/named_req/TriviallyCopyable‍

原文链接

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c90-rely-on-constructors-and-assignment-operators-not-memset-and-memcpy


觉得本文有帮助?欢迎点赞并分享给更多的人。

阅读更多更新文章,请关注微信公众号【面向对象思考】

发布了410 篇原创文章 · 获赞 677 · 访问量 31万+

猜你喜欢

转载自blog.csdn.net/craftsman1970/article/details/104973655