1

我有一种只能移动的类型,禁止复制。我想在某个系统中传递它,但我不确定将哪种签名用于在参数中采用该类型的函数。这种类型的对象必须移动到系统中,不应该进行任何复制。

例子:

#include <vector>
class Foo
{
public:
    Foo( std::string name ) : m_name( std::move( name ) ){}
    Foo( Foo&& other ) : m_name( std::move( other.m_name ) ){}
    Foo& operator=( Foo&& other ){ m_name = std::move( other.m_name ); }

    const std::string& name() const { return m_name; }
    // ...
private:
    Foo( const Foo& ) ;//= delete;
    Foo& operator=( const Foo& ) ;//= delete;
    // ...

    std::string m_name;
};

class Bar
{
public:

    void add( Foo foo )  // (1)
        // or...
    void add( Foo&& foo ) // (2)
    {
        m_foos.emplace_back( std::move(foo) ); // if add was template I should use std::forward?
    }


private:
    std::vector<Foo> m_foos;
};

void test()
{
    Bar bar;
    bar.add( Foo("hello") );

    Foo foo("world");
    bar.add( std::move(foo) );
}

(假设我正在移动对象,两个签名都在 VS2012 中编译)

应该首选 1 和 2 之间的哪个签名?

看起来两者都有效,但我认为必须有区别......

4

2 回答 2

4

从 xvalue 移动时,签名 #1 将花费 2 次移动构造,而从 xvalue 移动时,签名 #2 将仅花费 1 次移动构造。因此#2对我来说听起来更好。但只要搬家建设便宜,任何一个签名都可以完成工作。你想要:

  1. 真的很快,或者
  2. 速度是真快的两倍?

:-)

于 2012-09-14T00:25:50.063 回答
3

这取决于。

如果要将对象移动到函数中,请按值获取。编译器将自己进行移动,并且您将清楚地向调用者记录该函数移动传递的参数。如果您使用第二个,该函数可能会也可能不会移动参数,即使调用者必须使用std::move(foo). 这可能非常令人困惑。

如果您不想将对象移动到函数中,请使用左值引用。如果函数不发生变异,则设为 const,如果发生变异,则设为非 const。

于 2012-09-13T23:25:01.843 回答