首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >返回值优化和私有拷贝构造函数

返回值优化和私有拷贝构造函数
EN

Stack Overflow用户
提问于 2012-06-26 22:15:19
回答 3查看 1K关注 0票数 1

我写了一个简单的链表,因为最近的一次面试编程挑战向我展示了我的C++已经变得多么生疏。在我的列表中,我声明了一个私有拷贝构造函数,因为我想显式地避免制作任何拷贝(当然,还有懒惰)。当我想要通过值返回一个拥有我的列表之一的对象时,我遇到了一些麻烦。

代码语言:javascript
运行
复制
class Foo
{
   MyList<int> list;  // MyList has private copy constructor

   public:
      Foo() {};
};

class Bar
{
   public:
      Bar() {};

      Foo getFoo()
      {
         return Foo();
      }
};

当我试图通过值返回一个Foo对象时,我得到了一个编译器错误,告诉我MyList有一个私有的拷贝构造函数。返回值优化应该否定任何复制的需要吗?我需要写一个拷贝构造函数吗?我从来没有听说过移动构造函数,直到我开始寻找这个问题的解决方案,这是最好的解决方案吗?如果是这样的话,我就得好好研究一下了。如果不是,解决这个问题的首选方法是什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-06-26 23:17:07

基本的问题是,按值返回可能会复制。标准并不要求C++实现在其确实适用的地方应用复制省略。这就是为什么对象仍然必须是可复制的:以便实现何时使用它的决定不会影响代码是否格式良好。

无论如何,它不一定适用于用户可能想要的每个副本。例如,没有省略复制赋值。

我认为你的选择是:

  • 实现了一个正确的副本。如果有人因为复制而导致程序变慢,那么他们的分析器会告诉他们,如果你不想阻止他们,你不必让它成为你的工作。
  • 实现了一个正确的移动,但没有复制(仅限C++11)。
  • getFoo更改为接受一个Foo& (或者Foo*)参数,并通过某种方式改变其对象来避免复制。一个高效的swap将在这方面派上用场。如果像您的示例中那样,getFoo真的返回一个默认构造的Foo,那么这是非常没有意义的,因为调用者在调用getFoo.
  • return之前需要构造一个Foo,它是包装在智能指针中的动态分配的Fooauto_ptrunique_ptr。定义为创建对象并将独占所有权转移给其调用者的函数不应返回shared_ptr,因为它没有复制构造函数,而是在使用过的情况下以某种方式使其爆炸(无法链接、中止、抛出异常)。这样做的问题是(1)它注定会失败,但编译器什么也不会说,(2)你强制执行了实现的质量,所以如果有人出于某种原因故意禁用RVO,你的类就不能工作。

我可能漏掉了一些。

票数 3
EN

Stack Overflow用户

发布于 2012-06-26 22:16:59

该标准明确指出,构造函数仍然需要是可访问的,即使它被优化了。请参阅最近的草案中的12.8/32

在这种情况下,我更喜欢将对象设置为可移动和不可复制。它使所有权变得非常清晰和明确。

否则,您的用户始终可以使用shared_ptr。隐藏共享所有权充其量是一个有问题的想法(除非您可以保证所有值都是不可变的)。

票数 5
EN

Stack Overflow用户

发布于 2012-06-26 22:22:57

解决方案是实现您自己的复制构造函数,该构造函数将使用MyList的其他方法来实现复制语义。

...我想明确地避免制作任何副本

你必须做出选择。要么你不能复制一个对象,比如std::istream;然后你必须将这些对象保存在指针/引用中,因为它们可以被复制(在C++11中,你可以使用移动语义来代替)。或者实现复制构造函数,这可能比解决每个需要复制的地方的问题更容易。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11209326

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档