【问题标题】:Safe to use the compiler generated assignment operator?使用编译器生成的赋值运算符安全吗?
【发布时间】:2010-09-27 18:59:55
【问题描述】:

我正在使用 MFC 中的 CPoint 类。没有明确定义的赋值运算符或复制构造函数 (AFAIK)。然而,这行得通:

C点 p1(1, 2), p2; p2 = p1; // p2 现在等于 p1

我假设这是由于编译器生成的赋值运算符而自动工作的。对吗?

如果是这样,我可以确信这不会发生任何意外吗?在这种情况下,CPoint 非常简单,我认为一切都很好,但总的来说,这让我有点担心。这样做更好吗:

p2.SetPoint(p1.x, p2.x);

-cr

【问题讨论】:

    标签: c++ mfc variable-assignment


    【解决方案1】:

    这是安全的 - 如果不打算提供赋值运算符,那么 MFC 设计者可以确保它不可用(例如,通过将其设为私有)。

    IIRC 编译器将执行逐个成员的复制,因此对于像这样包含 POD 的类,您不会有问题。如果您有一个分配内存的类并且忽略覆盖 operator= 并执行深度复制,它可能会变得混乱。

    FWIW 不久前我问了一个关于编译器能做什么和不能做什么的问题:

    Why don't C++ compilers define operator== and operator!=?

    一些答案​​使阅读变得有趣。

    【讨论】:

      【解决方案2】:

      查找默认的复制构造函数:

      http://www.fredosaurus.com/notes-cpp/oop-condestructors/copyconstructors.html

      这并不是 CPoint 的特别之处。

      【讨论】:

        【解决方案3】:

        如果一个类是“简单的”,那么编译器生成的赋值运算符将起作用(按成员复制)。如果有一些成员需要更高级的逻辑(假设对象维护一个指向它所期望的私有缓冲区的内部指针),那么编译器生成的赋值运算符就会出现问题。 CPoint 只是存储了一个点的 x 和 y 坐标,所以你应该不会遇到问题。

        【讨论】:

        • 我假设对于一个广泛使用的库,如果默认值不起作用,开发人员将提供一个赋值运算符,或者声明一个私有赋值运算符以防止发出公共赋值运算符。简而言之,相信默认的。
        【解决方案4】:

        对于像 CPoint 这样的简单数据对象(您可以从 Visual Studio 安装随附的 MFC 源代码中看到,它只是一个带有一些便利功能的 Win32 POINT 结构),使用编译器生成的没有任何问题赋值运算符。

        但如前所述,默认赋值运算符是浅拷贝,如果结构包含指针(或包含包含指针但未定义赋值运算符的结构),则会给您带来麻烦。由于 CPoint 不符合该描述,因此它是安全的。

        【讨论】:

          【解决方案5】:

          内置的复制赋值操作符只是使用它们的复制赋值操作符依次复制每个成员。我假设 CPoint 不查看其文档是安全的(原因:如果不是,他们当然会提供自己的实现)。该点类应该只有两个成员(x 和 y),它们只是浮点数(或 int,取决于它的用途)。

          有人说这是“浅拷贝”,因为只拷贝了成员的值。如果您有指针成员,则会复制指针值,而不是指针指向的对象。

          【讨论】:

          • 所以内置的要求我知道我正在使用(但没有编写)的类的实现细节,并相信该类的未来版本不会发生重大变化。即使内置的很好,如果定义了一个明确的运算符,我仍然会感觉更好。
          • coryr,不,它不需要你知道。它要求该课程的作者知道,他真的应该:) 而且您可以相信该课程会做正确的事情。这就是课程的全部意义
          【解决方案6】:

          我不知道 MFC,但我可以猜测(或者):

          • CPoint 具有定义的赋值运算符(因此不是编译器生成的),或者
          • 编译器生成的赋值运算符在堆栈分配成员时起作用,因此它会按成员进行复制。

          【讨论】:

          • 栈分配与它无关;它同样适用于堆分配的 CPoint 对象。重要的一点是类中的数据是纯数据,没有所有权或唯一性约束。
          • 我说的是类的堆栈分配成员,而不是类的对象。
          • 我显然不明白您所说的“堆栈分配”是什么意思。你能扩展一下吗?
          【解决方案7】:

          是的。如果你在一个类上没有定义operator= 方法,编译器会为你生成一个,它只是简单地按位复制类中的字段。我记得,CPoint 只是{int x; int y},所以按位复制就可以了。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-10-31
            • 1970-01-01
            • 2013-03-21
            • 2014-02-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-15
            相关资源
            最近更新 更多