2

我定义了以下类:

class Action
{
    public: 
    Action(){ _bAllDone = false; }

    void AddMove( Move & m );
    private:
        std::deque<Move> _todo;
        bool _bAllDone;
};

成员 AddMove 定义如下:

void Action::AddMove( Move & m )
{ 
    _todo.push_back( m ); 
}

我注意到没有这个函数的引用参数,复制构造函数被调用了两次,而有一个引用参数它只被调用了一次。只调用一次复制构造函数而不是两次是使用引用参数的好理由吗?

4

3 回答 3

17

STL 中的 deque 类应该维护您传递给其 push_back 方法的元素的副本。这就是一个复制构造函数的来源。

如果你去掉 addMove() 中的引用,你将首先获得参数的副本(因此调用复制构造函数),然后当你推回时,你将获得第二个副本。

复制构造函数的双重调用是浪费的,所以引用是可取的。但是,您应该将 addMove() 的参数声明为 const 引用,以向调用者指示该元素不会被修改。在这样的保证下(假设你没有破坏它),通过引用传递对象是安全的,不用担心,也不会支付对象副本的代价。

于 2009-10-05T20:17:12.727 回答
4

对我来说似乎是一个很大的优势。如果您迭代地执行许多添加,事情可能会变得非常缓慢。实际工作量取决于 Move 的定义及其复制构造函数。微小的变化可能会对性能产生严重影响。无论哪种方式,通过副本传递仍然是两倍的工作量。

这样做的整体效果将取决于整个处理中有多少花费在此操作上。做一次,你永远不会注意到;做几千次,它可能很重要。但是,作为一般原则,请避免在可以安全引用的地方复制数据,尤其是因为在这种情况下没有特别的清晰度或复杂性问题 - 让它变快和让它变慢一样容易,所以你为什么要让它变慢?

于 2009-10-05T20:26:51.117 回答
0

必须是参考,否则您将产生不必要的(并且可能不正确的)参数副本。它也应该是const,否则你会不必要地限制你的调用者。

另请注意,带有前导下划线的名称保留给语言实现,因此您的程序实际上是“未定义的”。

高温高压

于 2009-10-05T21:22:49.323 回答