标签: rvalue-reference

为什么我需要在move-constructor的初始化列表中使用std :: move?

假设我有一个(普通的)类,它是可移动构造和可移动分配但不可复制构造或可复制分配:

class movable
{
  public:
    explicit movable(int) {}
    movable(movable&&) {}
    movable& operator=(movable&&) { return *this; }
    movable(const movable&) = delete;
    movable& operator=(const movable&) = delete;
};
Run Code Online (Sandbox Code Playgroud)

这很好用:

movable m1(movable(17));
Run Code Online (Sandbox Code Playgroud)

当然,这不起作用,因为m1它不是右值:

movable m2(m1);
Run Code Online (Sandbox Code Playgroud)

但是,我可以包m1std::move,它投射到一个右值引用,以使其工作:

movable m2(std::move(m1));
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.现在,假设我有一个(同样微不足道的)容器类,它包含一个值:

template <typename T>
class container
{
  public:
    explicit container(T&& value) : value_(value) {}
  private:
    T value_;
};
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用:

container<movable> c(movable(17));
Run Code Online (Sandbox Code Playgroud)

编译器(我试过clang 4.0和g ++ 4.7.2)抱怨我正在尝试movablecontainer初始化列表中使用已删除的复制构造函数.同样,包裹valuestd::move使得它的工作:

    explicit container(T&& value) : value_(std::move(value)) {} …
Run Code Online (Sandbox Code Playgroud)

c++ rvalue-reference move-constructor move-semantics c++11

14
推荐指数
2
解决办法
2600
查看次数

rvalue引用是否有reference_wrapper <>?

我想知道如何做到以下几点

void f(string &&s) { 
  std::string i(move(s)); 
  /* other stuff */ 
} 

int main() { 
  std::string s; 
  bind(f, s)(); // Error.
  bind(f, move(s))(); // Error.
  bind(f, ref(s))(); // Error.
}
Run Code Online (Sandbox Code Playgroud)

如何传递rvalue引用并将其作为rvalue引用(可能包装)存储在调用包装器中?我知道我可以手动编写一个类似于std::reference_wrapper<>具有转换功能的类T&&,但我宁愿避免这种情况并使用标准技术.


我像AProgrammer推荐的那样实现了它:

template<typename T> struct adv { 
  T t; 
  explicit adv(T &&t):t(forward<T>(t)) {} 
  template<typename ...U> T &&operator()(U &&...) { 
    return forward<T>(t); 
  } 
}; 

template<typename T> adv<T> make_adv(T &&t) { 
  return adv<T>{forward<T>(t)}; 
}

namespace std { 
  template<typename T> 
  struct is_bind_expression< adv<T> > : std::true_type {}; 
} 
Run Code Online (Sandbox Code Playgroud)

现在我可以说 …

c++ rvalue-reference stdbind c++11

13
推荐指数
2
解决办法
2974
查看次数

将函数的返回类型声明为T &&是没有意义的吗?

众所周知,在大多数情况下,T&&意味着"这是一个临时对象".但是,如果想要从函数返回临时对象,他/她可以按如下方式声明函数:

template<class T>
T f()
{
    T t;
    ......

    return t;
}
Run Code Online (Sandbox Code Playgroud)

或(注意:不正确)

template<class T>
T&& f()
{
    T t;
    ......

    return t;
}
Run Code Online (Sandbox Code Playgroud)

但我认为后者是过度的,因为前者足够向后兼容.

然而,我也发现它std::forward()的返回类型被声明为T &&,所以我确信我对此的理解是不完整的.

我真正的问题是:我们何时何地将函数的返回类型声明为T &&?

c++ temporary return-type rvalue-reference c++11

13
推荐指数
1
解决办法
503
查看次数

何时在`std :: move()`函数中调用移动构造函数?

该功能std::move()定义为

template<typename T>
typename std::remove_reference<T>::type&& move(T && t)
{ 
    return static_cast<typename std::remove_reference<T>::type&&>( t ); 
}
Run Code Online (Sandbox Code Playgroud)

有四个地方我可以想象要调用的移动构造函数:

  1. 参数传递时.
  2. 演员表演时.
  3. 返回结果时.
  4. 不在std::move()函数本身,但可能在返回的引用最终到达的位置.

我敢打赌4号,但我不是百分百肯定,所以请解释你的答案.

c++ rvalue-reference move-semantics c++11

13
推荐指数
1
解决办法
688
查看次数

与右值交换

假设我希望swap它适用于rvalues,并且不想为rvalue/lvalue引用的所有组合编写4个版本(rvalue/rvalue版本有点无意义,但它没有伤害).我想出了这个:

template <typename A, typename B>
struct is_same_no_ref
    : std::is_same<
        typename std::remove_reference<A>::type,
        typename std::remove_reference<B>::type
    >
{};

template <typename A, typename B,
    typename = typename std::enable_if<is_same_no_ref<A, B>::value>::type
>
inline void my_swap(A&& a, B&& b) {
    typename std::remove_reference<A>::type t = std::move(a);
    a = std::move(b);
    b = std::move(t);
}
Run Code Online (Sandbox Code Playgroud)

这似乎按预期工作.这个可以吗?或者我错过了一些让我后来受苦的重要事情?

c++ swap rvalue-reference move-semantics

13
推荐指数
1
解决办法
1802
查看次数

即使XZY具有非复制约束,构造助手make_XYZ也允许RVO和类型推导

UPDATE1: C++ 17构造附加型扣-这并不意味着自由功能是较差的溶液.

UPDATE2: C++ 17增加了保证副本省略(副本甚至没有在概念上发生).因此,使用C++ 17,我的代码实际上可以工作并具有最佳性能.但Martinho使用支撑初始化来获得返回值的代码仍然是我认为的更清洁的解决方案.但请查看Barry的回答以及TC的评论

旧帖子:类型推导不适用于构造函数(至少在包含C++ 11之前).常见的解决方案是依靠RVO(返回值优化)并编写make_XYZ模板函数,将其参数转发给构造函数.一个例子是std::make_tuple.

任何模板acrobat谁知道一个解决方法,以便在nocopy策略阻碍时使其工作?有效的解决方案仍然必须允许RVO发生.

另外,对于任何make_XYZ的要求是否会随C++ 14消失?

#include <iostream>

template <typename T>
struct XYZ
{
    // remove following two lines to make the code compile
    XYZ (XYZ const & rhs) = delete; 
    XYZ (XYZ && rhs) = delete; 
    T i;
    XYZ (T i):i(i)
    {
    }
};

template <typename T>
XYZ<T> make_XYZ (T && i)
{
    return XYZ<T>(std::forward<T>(i));
}

int main ()
{
    auto x = make_XYZ(1);
    std::cout << x.i << …
Run Code Online (Sandbox Code Playgroud)

c++ rvalue-reference c++11 return-type-deduction c++17

13
推荐指数
1
解决办法
715
查看次数

C++是否可以重载右值引用的一元减运算符?

有可能辨别这两种方法吗?如果在这种情况下看起来完全可重复使用,是否应该改变右值?

TYPE a;
TYPE b = -a;      // unary operator- of a TYPE& aka lvalue ref
TYPE c = -(a+b);  // unary operator- of a TYPE&& aka rvalue ref
Run Code Online (Sandbox Code Playgroud)

c++ operator-overloading unary-operator rvalue-reference

13
推荐指数
2
解决办法
667
查看次数

成员变量的类型应该取决于构造函数参数的类型

我尝试A按如下方式定义一个类:

template< typename T >
class A
{
  public:
    A( T elem )
      : _elem( elem )
    {}

  private:
    TYPE _elem; // "TYPE" should be either "T" in case "elem" is an r-value or "T&" in case "elem" is an l-value.
};
Run Code Online (Sandbox Code Playgroud)

在这里,我希望_elem有一个类型T,以防构造函数的参数elem是一个r值或者T&case中的类型elem是一个l值.

有谁知道这是如何实现的?

c++ lvalue rvalue-reference type-deduction

13
推荐指数
1
解决办法
347
查看次数

临时对象的数据成员是C++ 11中的xvalue吗?

#include <vector>

using namespace std;

struct A
{
    vector<int> coll;
};

void f(const vector<int>&){}
void f(vector<int>&&){}

int main()
{
    f(A().coll); // Is "A().coll" an xvalue? 
}
Run Code Online (Sandbox Code Playgroud)

C++ 11保证f(A().coll)会打电话void f(vector<int>&&)吗?

c++ rvalue rvalue-reference move-semantics c++11

13
推荐指数
1
解决办法
359
查看次数

左值转换的左值?

为什么不能将rvalues转换为左值?但是可以在相反方向进行转换.技术上rvalues确实有内存地址,不是吗?

c++ type-conversion lvalue rvalue-reference c++11

13
推荐指数
2
解决办法
4897
查看次数