16

我有一个对向量进行操作的代码:

template<typename T>
void doVector(vector<T>& v, T&& value) {
    //....
    v.push_back(value);
    //...
}

对于正常情况push_back,我需要使用forward(value)move(value)还是只需要value(根据新的 C++11)?以及它们如何影响性能?

例如,

v.push_back(forward<T>(value));
4

4 回答 4

18

当第二个参数是左值时,当前代码将无法编译,因为T&&结果会是X&which 意味着T需要是X&,这反过来意味着std::vector<T>将成为std::vector<X&>与第一个参数不匹配的std::vector<X> &. 因此,这是一个错误。

我会使用两个模板参数:

template<typename T, typename V>
void doVector(vector<T> & v, V && value) 
{
    v.emplace_back(std::forward<V>(value));
}

由于V可以使用不同的类型T,所以更有emplace_back意义,因为它不仅解决了问题,而且使代码更通用。:-)

现在进行下一个改进:由于我们使用emplace_backwhichT从参数创建类型的对象value(可能使用构造函数),我们可以利用这一事实,并使其成为可变参数函数:

template<typename T, typename ...V>
void doVector(vector<T> & v, V && ... value) 
{
    v.emplace_back(std::forward<V>(value)...);
}

这更通用,因为您可以将其用作:

struct point
{
    point(int, int) {}
};

std::vector<point> pts;
doVector(pts, 1, 2);

std::vector<int> ints;
doVector(ints, 10);

希望有帮助。

于 2013-08-13T16:41:09.397 回答
7
  1. forward(value)如果您需要完美的转发含义,则使用它,保留诸如左值,右值之类的东西。

  2. 转发非常有用,因为它可以帮助您避免为 l-val、r-val 和引用参数的不同组合的函数编写多个重载

  3. move(value)实际上是一种将左值转换为右值的类型转换运算符

  4. 在性能方面,两者都避免制作额外的对象副本,这是主要的好处。

所以他们真的做了两件不同的事情


当您说正常的 push_back 时,我不确定您的意思,这是两个签名。

void push_back( const T& value );
void push_back( T&& value );

第一个你可以传递任何正常的 l-val,但第二个你必须“移动”一个 l-val 或转发一个 r-val。请记住,一旦移动 l-val,您将无法使用它

值得一提的是,这里有一个资源似乎很好地解释了 r-val-refs 的概念以及与它们相关的其他概念。

正如其他人所建议的那样,您也可以切换到使用 emplace back,因为它实际上完美地将参数转发给对象的构造函数,这意味着您可以随意传递它。

于 2013-08-13T16:37:33.883 回答
6
  • 传递作为转发引用的参数时,请始终使用std::forward.
  • 当传递一个r-value参数时,使用std::move.

例如

template <typename T>
void funcA(T&& t) {
    funcC(std::forward<T>(t)); // T is deduced and therefore T&& means forward-ref.
}

void funcB(Foo&& f) {
    funcC(std::move(f)); // f is r-value, use move.
}

这是 Scott Meyers 的精彩视频,解释了转发引用(他称之为通用引用)以及何时使用完美转发和/或std::move

C++ 及以后 2012:Scott Meyers - C++11 中的通用引用

另请参阅此相关问题以获取有关使用的更多信息std::forward使用转发的优势

于 2013-08-13T16:50:41.870 回答
0

http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Scott-Meyers-Universal-References-in-Cpp11

那个视频,IMO,对何时使用 std::forward 和何时使用 std::move 有最好的解释。它提出了通用参考的想法,这是 IMO 用于推理移动语义的非常有用的工具。

于 2013-08-13T17:47:03.263 回答