我应该使用std :: move或std :: forward在移动ctors /赋值运算符? [英] Should I use std::move or std::forward in move ctors/assignment operators?

查看:187
本文介绍了我应该使用std :: move或std :: forward在移动ctors /赋值运算符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

除非我错了似乎要么工作正常 - 是否有一个最佳实践的理由喜欢一个比另一个?



示例:

  struct A 
{
A(){}
A(const A&){std :: cout < A(const A&)\\\
; }
A(A&&){std :: cout<< A(A&&)\\\
; }
};

struct B
{
B(){}
B(const B& right):x(right.x){std :: cout< ; B(const B&)\\\
; }
B(B&& right):x(std :: forward< A>(right.x)){std :: cout< B(B&&)\\\
; }

A x;
};

struct C
{
C(){}
C(const C& right):x(right.x){std :: cout< ; C(const C&)\\\
; }
C(C&& right):x(std :: move(right.x)){std :: cout< C(&&)\\\
; }

A x;
};

struct D
{
D(){}
D(const D& right):x(right.x){std :: cout< ; D(const D&)\\\
; }
D(D&& right):x(right.x){std :: cout< D(D&&)\\\
; }

A x;
};

int main()
{
std :: cout< --- B Test --- \\\
;
B b1;
B b2(std :: move(b1));
std :: cout<< --- C Test --- \\\
;
C c1;
C c2(std :: move(c1));
std :: cout<< --- D Test --- \\\
;
D d1;
D d2(std :: move(d1));
}

输出:



p $ p> --- B测试---
A(A&&)
B(B& -
A(A&&)
C(C&&)
--- D Test ---
A(const A&)
问题是:你可以通过下面的方法来解决这个问题:D(D&这些真的是移动的构造函数/赋值运算符类吗?

  struct X {
X(X&&;); // move ctor#1

template< class T>
X(T&&;); // perfect forwarding ctor#2

X& operator =(X&&;); // move assignment operator#3

template< class T>
X& operator =(T&&;); //完美的转发屁股。运算符#4
};

真实 move ctor(#1)和移动赋值运算符#3),你永远不会使用 std :: forward ,因为,如你正确评估,你将永远移动。



请注意,如果没有完美的转发模板( T&& ), std :: forward 这正是#2和#4的情况。在这里,你永远不会使用 std :: move ,因为你不知道实际上是否有一个右值(A-OK)或左值(不是那么多)。



请参阅我的这个答案,了解如何 std :: forward 实际上可以工作。


Unless I'm wrong it seems like either works just fine - is there a best practice reason to prefer one over the other?

Example:

struct A
{
    A(){}
    A(const A&){ std::cout << "A(const A&)\n"; }
    A(A&&){ std::cout << "A(A&&)\n"; }
};

struct B
{
    B(){}
    B(const B& right) : x(right.x){ std::cout << "B(const B&)\n"; }
    B(B&& right) : x(std::forward<A>(right.x)){ std::cout << "B(B&&)\n"; }

    A x;
};

struct C
{
    C(){}
    C(const C& right) : x(right.x){ std::cout << "C(const C&)\n"; }
    C(C&& right) : x(std::move(right.x)){ std::cout << "C(C&&)\n"; }

    A x;
};

struct D
{
    D(){}
    D(const D& right) : x(right.x){ std::cout << "D(const D&)\n"; }
    D(D&& right) : x(right.x){ std::cout << "D(D&&)\n"; }

    A x;
};

int main()
{
    std::cout << "--- B Test ---\n";
    B b1;
    B b2(std::move(b1));
    std::cout << "--- C Test ---\n";
    C c1;
    C c2(std::move(c1));
    std::cout << "--- D Test ---\n";
    D d1;
    D d2(std::move(d1));
}

Output:

--- B Test ---
A(A&&)
B(B&&)
--- C Test ---
A(A&&)
C(C&&)
--- D Test ---
A(const A&)
D(D&&)

解决方案

The question is: Are those really the move constructor / assignment operator for the class? Or do they only look like that from the corner of your eye?

struct X{
  X(X&&); // move ctor #1

  template<class T>
  X(T&&); // perfect forwarding ctor #2

  X& operator=(X&&); // move assignment operator #3

  template<class T>
  X& operator=(T&&); // perfect forwarding ass. operator #4
};

In a real move ctor (#1) and move assignment operator (#3), you will never use std::forward, since, as you correctly assessed, you will always move.

Note that std::forward never makes sense without a perfect forwarding template (T&&). That is exactly the case for #2 and #4. Here, you will never use std::move, since you don't know if you actually got an rvalue (A-OK) or an lvalue (not so much).

See this answer of mine for an explanation of how std::forward actually works.

这篇关于我应该使用std :: move或std :: forward在移动ctors /赋值运算符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆