在 C++ 中编写复制构造函数和赋值运算符的清单

发布于 2024-07-07 03:51:11 字数 54 浏览 7 评论 0原文

请写出 C++ 中复制构造函数和赋值运算符需要执行的任务列表,以保持异常安全、避免内存泄漏等。

Please write a list of tasks that a copy constructor and assignment operator need to do in C++ to keep exception safety, avoid memory leaks etc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

三生一梦 2024-07-14 03:51:11

首先确保您确实需要支持复制。 大多数时候情况并非如此,因此禁用两者是正确的方法。

有时,您仍然需要在多态层次结构中的类上提供重复项,在这种情况下:禁用赋值运算符,编写(受保护的?)复制构造函数,并提供虚拟clone()函数。

否则,如果您正在编写一个值类,那么您将回到 Coplien 正交规范形式的土地。 如果您有一个无法简单复制的成员,则需要提供一个复制构造函数、一个析构函数、一个赋值运算符和一个默认构造函数。 这个规则可以被细化,例如:The Law of the Big Two

I'还建议您查看有关赋值运算符的 C++ 常见问题解答,以及 copy-and-swap 习语 和在 GOTW

First be sure you really need to support copy. Most of the time it is not the case, and thus disabling both is the way to go.

Sometimes, you'll still need to provide duplication on a class from a polymorphic hierarchy, in that case: disable the assignment operator, write a (protected?) copy constructor, and provide a virtual clone() function.

Otherwise, in the case you are writing a value class, you're back into the land of the Orthogonal Canonical Form of Coplien. If you have a member that can't be trivially copied, you'll need to provide a copy-constructor, a destructor, an assignment-operator and a default constructor. This rule can be refined, see for instance: The Law of The Big Two

I'd also recommend to have a look at C++ FAQ regarding assignment operators, and at the copy-and-swap idiom and at GOTW.

笑咖 2024-07-14 03:51:11

编译器生成的版本适用于大多数情况。

当您的对象包含 RAW 指针(不具有 RAW 指针的论点)时,您需要仔细考虑一下问题。 所以你有一个RAW指针,第二个问题是你是否拥有该指针(它是否被你删除)? 如果是这样,那么您将需要应用 4 的规则。

拥有超过 1 个 RAW 指针变得越来越难以正确执行(复杂性的增加也不是线性的 [但这是观察性的,我没有真正的统计数据来支持该声明])。 因此,如果您有超过 1 个原始指针,请考虑将每个指针包装在自己的类中(某种形式的智能指针)。

规则 4:如果一个对象是 RAW 指针的所有者,那么您需要定义以下 4 个成员,以确保正确处理内存管理:

  • 构造函数
  • 复制构造函数
  • 赋值运算符 析
  • 构函数

如何定义这些成员取决于具体情况。 但需要注意的事项:

  • 默认构造:将指针设置为 NULL
  • 复制构造函数:使用复制和交换思想来提供“强异常保证”
  • 赋值运算符:检查对 self 的
  • 赋值 析构函数:防止从析构函数传播异常。

The compiler generated versions work in most situations.

You need to think a bit harder about the problem when your object contains a RAW pointer (an argument for not having RAW pointers). So you have a RAW pointer, the second question is do you own the pointer (is it being deleted by you)? If so then you will need to apply the rule of 4.

Owning more than 1 RAW pointer becomes increasingly hard to do correctly (The increase in complexity is not linear either [but that is observational and I have no real stats to back that statement up]). So if you have more than 1 RAW pointer think about wrapping each in its own class (some form of smart pointer).

Rule of 4: If an object is the owner of a RAW pointer then you need to define the following 4 members to make sure you handle the memory management correctly:

  • Constructor
  • Copy Constructor
  • Assignment Operator
  • Destructor

How you define these will depend on the situations. But things to watch out for:

  • Default Construction: Set pointer to NULL
  • Copy Constructor: Use the Copy and Swap ideum to provide to the "Strong Exception Guarantee"
  • Assignment operator: Check for assignment to self
  • Destructor: Guard against exceptions propagating out of the destructor.
请别遗忘我 2024-07-14 03:51:11

我不知道这里的异常安全,但我走这条路。 让我们假设它是一个模板化数组包装器。 希望能帮助到你 :)

Array(const Array& rhs)
    {
        mData = NULL;
        mSize = rhs.size();
        *this = rhs;
    }

    Array& operator=(const Array& rhs)
    {
        if(this == &rhs)
        {
            return *this;
        }

        int len = rhs.size();

        delete[] mData;

        mData = new T[len];

        for(int i = 0; i < len; ++i)
        {
            mData[i] = rhs[i];
        }

        mSize = len;

        return *this;
    }

I have no idea about exception safely here but I go this way. Let's imagine it's a templated array wrapper. Hope it helps :)

Array(const Array& rhs)
    {
        mData = NULL;
        mSize = rhs.size();
        *this = rhs;
    }

    Array& operator=(const Array& rhs)
    {
        if(this == &rhs)
        {
            return *this;
        }

        int len = rhs.size();

        delete[] mData;

        mData = new T[len];

        for(int i = 0; i < len; ++i)
        {
            mData[i] = rhs[i];
        }

        mSize = len;

        return *this;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文