4

我正在使用 C++11 开始一个新项目,并且刚刚发现了delete可以防止意外调用复制构造函数等的关键字。是否有一组“推荐”的删除我可以全局执行以提高类型安全性,例如防止表达式中的有符号到无符号转换?我应该默认在我的所有课程中delete执行所有 5 项操作吗?delete

仅供参考,这个程序需要高性能(这就是我多年来第一次使用 C++ 的原因)而且我想复制任何东西的次数很少,所以复制通常是一个错误,尽管不是 100% 的时间,所以我对这个特定案例以及其他程序的一般案例感兴趣。我可以潜在delete地使用复制构造函数并添加一个单独的方法,该方法在我确实需要副本的极少数情况下复制对象。这是个好主意吗?

4

3 回答 3

7

是否有一组“推荐”的删除我可以全局执行以提高类型安全性,例如防止表达式中的有符号到无符号转换?

不,您当然不能通过删除任何内容来阻止整数转换。

我是否应该默认删除我可以在所有课程中删除的所有 5 个操作?

不!删除的析构函数将无法销毁任何东西!

此外,删除移动构造函数很少有意义。如果您的类型可以廉价地移动,那么允许移动(例如,当按值返回对象时,或按值作为函数参数传递临时对象时)通常是一件好事,即使您不想允许复制。人为地限制该类型的用户移动它是有效的,这只是烦人的,并没有提供任何优势。

您似乎陷入了看到某个功能可用并认为应该使用它的陷阱。来自The Old Man and the C的以下引用似乎是相关的:

关于早期故事的最后一个轶事,其中有人使用了 int 参考参数。在讨论这篇论文时,程序员的评论是——“嗯,这个特性在语言中,所以我想我应该使用它。”。我们认为这不是使用 C++ 特性的充分标准。只有在可以证明它是有益的时候才应该使用一个特性。一座山被攀登“因为它在那里”。对于 C++ 特性,同样的情况不应该成立。它们的存在并不是使用的理由。

至于你的最后一个问题:

我可能会删除复制构造函数并添加一个单独的方法,该方法在我确实需要副本的极少数情况下复制对象。这是个好主意吗?

...也许...这可能是可以证明已删除的复制构造函数有用的情况。但我一般会说不,不要那样做,因为它很难将对象存储在容器中,例如。最好只仔细编写代码以避免不需要的副本。如果您没有这样做并且已经证明您确实在制作意外副本,那么可能会重新考虑删除复制构造函数。

但是你不应该仅仅因为你已经了解了这个特性就“默认”删除操作。它应该常见,= default而不是= delete用于模拟一些非典型行为的类,例如资源的唯一所有权。

于 2015-03-10T11:57:28.523 回答
5

根据我的经验,在某些情况下删除某些构造函数或运算符是有意义的。

例如,考虑unique_ptr类。unique_ptr's 用于只希望一个指针访问某种数据(可能在多线程应用程序中)时使用,因此让多个unique_ptr's 浮动围绕它们都指向同一个对象是没有意义的。

为了防止不必要的复制分配,默认情况下,unique_ptr课程中包含以下内容:

unique_ptr& operator= (const unique_ptr&) = delete;

这是从类中删除运算符有意义的一个实例。我会说这是一个非常判断的电话。我的一般规则是问自己,“类的客户端是否绝对不应该使用 x 运算符或 y 构造函数?” 如果你决定 x 或 y 实际上不应该(或者可能只是很少)被使用,那么,在我看来,继续删除所述操作符/构造函数可能是有意义的。

于 2015-03-10T07:42:03.873 回答
1

是的,这个想法似乎不错。声明所有不需要的特殊方法delete将禁用它们,就像你想要的那样。

但是,这在delete发明之前也是可能的——boost::noncopyable在 c++11 发布之前用于此目的。即使使用 c++11,继承 fromboost::noncopyable似乎比用 . 标记所有不需要的特殊成员更容易(键入更少)= delete

此外,由于您提到“防止有符号转换为无符号转换” - 您应该知道内置类型(如intto unsigned)之间的转换是内置的,不能被禁用。不涉及用户定义类型的转换规则在 C 和 C++ 中是相同的(有少量例外),并且不能更改。您可以做的最好的事情是将编译器配置为“发出所有警告”并可能“将警告视为错误”。

于 2015-03-10T11:13:32.290 回答