将参数传递为const&或者&&

时间:2013-10-12 15:51:24

标签: c++ forward rvalue

考虑以下内容,其中一些内容通过多个层添加到矢量中:

class A {
public:
  void Add(Content c) {
    // Considerable amount of checking code here.
    v.push_back(c);
  }
private:
  std::vector<Content> v;
};

class B {
public:
  void Add(Content c) {
    // Considerable amount of additional code here.
    a.Add(c);
  }
private:
  A a;
};

class C {
public:
  void Add(Content c) {
    // Considerable amount of additional code here.
    b.Add(c);
  }
private:
  B b;
};

这可以继续,但你明白这一点。我希望通过复制或移动来添加内容,即通过push_back(const Content&amp;)或push_back(Content&amp;&amp;)。呼叫者应该能够呼叫:

C c;
Content z;
c.Add(z);

c.Add(move(z));

并获得最少数量的副本。

有没有一种方法可以实现这一点而无需复制其他代码并且无需添加函数模板函数?

2 个答案:

答案 0 :(得分:1)

为rvalue和lvalue重载两个方法是一种方法:

void Add(const Content & c);
void Add(Content && c);

使用完美转发可以避免两次重载。您应该制作所有add方法:

template<typename T>
void add(T&& a)
{
   b.Add(std::forward<T>(a));
}

另一种更好(IMO)的方法是使Content可移动。如果Content是真实类(不是模板的占位符),则可以执行此操作:

class Content
{
public:
  Content(const Content &);
  Content(Content &&);

  Content &operator=(Content);  // Copy and swap idiom!

  ~Content();
};

之后,您可以重写Add方法,如下所示:

 void Add(Content c) {
    b.Add(std::move(c));
          ^^^^^^^^^^^^
 }

这种方法的优点是,您可以从呼叫方透明移动或复制。

答案 1 :(得分:0)

您可以添加两个带下一个签名的方法:

void Add(Content && c);
void Add(Content & c);

其他选项是通用引用,但您需要模板。