C++ 中的三法则

Rule of Three in C++

提问人:squashed.bugaboo 提问时间:6/14/2012 最后编辑:Communitysquashed.bugaboo 更新时间:6/14/2012 访问量:1899

问:

我读过《三法则,什么是三法则?》总结如下:

如果需要显式声明析构函数、复制构造函数或复制赋值 运算符,您可能需要显式声明所有三个。

我的问题是:在 C++ 应用程序中,我有一个管理资源的类(有一个处理删除指针的析构函数)。我知道应用程序到处都使用赋值运算符,但我绝对确定在复制构造函数的应用程序中没有用法,即类型的用法,因此在这种情况下,我是否仍然需要同时实现赋值运算符和复制构造函数?还是仅凭赋值运算符就足够了?赋值运算符是否有可能以某种方式使用复制构造函数?Class c(..); Class d(c);

欣赏你的想法。

C++ 三法则

评论

0赞 chris 6/14/2012
即使你现在不使用某些东西,你也可能决定以后使用,并最终陷入困境。
2赞 Samy Vilar 6/14/2012
C++ 如果没有为您指定,它将创建一个默认构造函数/复制构造函数/默认析构函数,大多数时候它会做一些非常糟糕的事情,具体取决于您的结构,如果显式/隐式调用。
0赞 AJG85 6/14/2012
即使你绝对确定它现在没有被使用,它也可能在以后使用(比如说,如果你从函数返回对象)......该规则的要点是,当一个的默认实现不够好时,其他的默认实现通常也不会足够好,因此最好涵盖所有基础。
0赞 roottraveller 10/17/2016
什么是三法则的可能副本?

答:

4赞 Doug T. 6/14/2012 #1

我绝对确定在复制构造函数的应用中没有用法,即使用类型 c(..);d(c)类

您是否知道以下代码

Foo c;
Foo b = c;

调用复制构造函数而不是赋值运算符?为了安全起见,我会实现复制构造函数。

评论

0赞 squashed.bugaboo 6/14/2012
谢谢@Doug:是的,我知道这个事实,但我只有 Foo& b = c 等用法。
3赞 ildjarn 6/14/2012
更好的是,使类不可复制,并让编译器/链接器告诉您是否违反了自己的不变性。零开销,零努力。
13赞 Stuart Golodetz 6/14/2012 #2

如果您知道不会使用复制构造函数,则可以通过将其私有化和未实现来表达它,因此:

class C
{
private:
    C(const C&); // not implemented
};

(在 C++11 中,您可以使用新语法)。也就是说,只有在您绝对确定永远不需要它时,您才应该这样做。否则,你最好实现它。重要的是不要只是保持原样,因为在这种情况下,编译器将提供一个默认的成员复制构造函数,该构造函数将做错误的事情 - 这是一个等待发生的问题。= delete

在某种程度上,这取决于类的用途 - 例如,如果你正在编写一个属于库的类,那么出于一致性原因实现复制构造函数更有意义。你不知道你的类将如何被使用。

评论

0赞 squashed.bugaboo 6/14/2012
谢谢@Golodetz。我喜欢这个主意。会尝试一下。
0赞 squashed.bugaboo 6/14/2012
这在结构中也有效吗?我也有一些管理资源的结构。
2赞 Stuart Golodetz 6/14/2012
是的,它也适用于结构。结构就像一个类,除了默认的公共访问和公共继承。也就是说,如果你正在管理资源,那么使用这个关键词可以说是更习惯的 - 在结构中管理资源在某种程度上感觉很奇怪。结构是 C 的宿醉,尽管 C++ 中的结构和类之间几乎没有区别,但继续主要以类似 C 的方式使用它们仍然更常见。class
0赞 squashed.bugaboo 6/14/2012
谢谢,这不在我的代码中。.而且它是巨大的。但很高兴知道这也适用于结构体。谢谢。
0赞 AJG85 6/14/2012
@squashed.bugaboo 结构和类之间唯一真正的区别是,结构是默认的公共范围,而类是默认的私有范围。
1赞 David 6/14/2012 #3

在几乎所有情况下,编译器都会为你生成这些方法,你不需要做任何事情。但是,如果隐式生成的复制构造函数/赋值运算符不能执行您想要的操作,并且从设计上讲,您的类能够被复制是有意义的,那么无论您是否同时使用它们,您都应该显式提供复制 ctor 和赋值运算符(作为良好做法)。

如果从设计上讲,你的类是不可复制的,你可以声明但不能定义 copy ctor/assignment op。

评论

0赞 Ian Ringrose 1/10/2014
如果在字段中存储了任何指针,则默认值在 99% 的情况下都是错误的。
0赞 David 1/10/2014
@IanRingrose 仅适用于过时的C++做法。如今,原始指针永远不应该代表所有权。
0赞 Ian Ringrose 1/10/2014
问题是世界上大多数C++代码都已经过时了,想想 MFC 还有多少!!
0赞 David 1/10/2014
@Ian 与过时的代码交互不是促进继续使用过时做法的借口。不过不错的尝试。
0赞 Ian Ringrose 1/10/2014
有什么理由对大多数软件使用 C++ 而不是 Java 或 C#,除非系统中有过时的代码?