std :: forward和带有非const引用参数的构造函数

Kla*_*ens 7 c++ perfect-forwarding c++11

Rvalue References的简介中,提出了完美转发作为将rvalue 5转发到具有非const引用参数的构造函数的理想解决方案.

但:

#include <memory>
#include <iostream>
#include <utility>

template <class T, class A1>
std::shared_ptr<T> factory(A1&& a1) {
   return std::shared_ptr<T>(new T(std::forward<A1>(a1)));
}

class X {
public:
    X(int& i){
        std::cout<<"X("<<i<<")\n";
    }
};


int main() {
    std::shared_ptr<X> p = factory<X>(5);
}
Run Code Online (Sandbox Code Playgroud)

在XCode 4.2和G ++ 4.6.1中失败no known conversion from int to int&,而:

template <class T, class A1>
std::shared_ptr<T> factory(A1&& a1) {
   return std::shared_ptr<T>(new T(/*no forwarding*/a1));
}
Run Code Online (Sandbox Code Playgroud)

编译.我弄错了什么?

Naw*_*waz 5

提出了完美转发作为将rvalue 5转发到具有非const引用参数的构造函数的理想解决方案.

我不认为完美转发意味着.如果这篇文章是正确的,这篇文章甚至不能暗示这一点.

相反,它意味着它可以将rvalue引用转发为rvalues,因此可以调用move-constructor或带有rvalue引用的构造函数/函数.

所以你应该试试这个:

class X {
public:
    X(int& i){
        std::cout<<"X("<<i<<")\n";
    }

    //this is a constructor which takes rvalue references
    X(int&& i){ 
        std::cout<<"X("<<i<<")\n";
    }
};
Run Code Online (Sandbox Code Playgroud)

也就是说,factory应该调用第二个构造函数,而不是你编写的构造函数.

顺便说一下,在这种情况下,构造函数没有多大意义,因为参数类型int是基本类型.

Rvalue referencs作为参数类型用于定义管理资源的类的移动构造函数和移动分配.如果用户定义的类不管理资源,则移动语义没有意义.

  • 对于`在这种情况下,移动构造函数没有多大意义 (3认同)

R. *_*des 5

您不能将rvalues绑定到非const左值引用.该文章并未建议使用完美转发,因为这是不可能的.完美转发左值作为左值,右值作为右值:

这里,forward保留传递给工厂的参数的左值/右值.如果将右值传递给工厂,则在前向函数的帮助下将右值传递给T的构造函数.类似地,如果将左值传递给工厂,它将作为左值转发给T的构造函数.

由于示例中的构造函数只接受左值,因此只能将左值传递给工厂函数.传递一个右值会将它作为一个右值转发,并且由于没有办法将右值传递给该构造函数,因此格式错误.