C++ 前向参考混淆

C++ 前向参考混淆,c++,c++11,c++14,C++,C++11,C++14,关于下面的代码,我不理解为什么调用移动构造函数时同时使用左值和右值。当我将lvalue传递给push方法时,我希望打印copy-ctor #include <iostream> #include <string> #include <vector> using namespace std; class my_obj { public: my_obj() { cout << "default ctor\n";

关于下面的代码,我不理解为什么调用
移动构造函数
时同时使用
左值
右值
。当我将
lvalue
传递给
push
方法时,我希望打印
copy-ctor

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class my_obj
{
public:
    my_obj()
    {
        cout << "default ctor\n";
    }

    my_obj(const my_obj& other)
    {
        cout << "copy ctor\n";
    }

    my_obj(my_obj&&  other)
    {
        cout << "move ctor\n";
    }      
};

class test
{
public:
    template<typename T>
    void push(T&& object)
    {
         print(forward<T>(object));
    }

    template<typename T>
    void print(T&& a)
    {
        cout << "move\n";
        my_obj temp = forward<T>(a);
    }

    template<typename T>
    void print(T& a)
    {
        cout << "val\n";
        my_obj temp = forward<T>(a);
    }
};


int main()
{
    my_obj obj;
    test f;

    f.push(obj); // why is move ctor called here? shouldnt it be copy ctor since not rvalue
    cout << "\nPUSHING TEMP\n\n";
    f.push(my_obj {});
}

调用移动构造函数是因为您正在使用
std::forward
而没有转发引用(请不要这样做)。基本上,这条线是罪魁祸首:

my_obj temp = forward<T>(a);

因此,您正在将
a
强制转换为右值引用,并且右值具有移动语义,因此您可以看到正在调用移动构造函数。您基本上得到了
std::move
的行为,调用move构造函数是因为您使用的
std::forward
没有转发引用(请不要这样做)。基本上,这条线是罪魁祸首:

my_obj temp = forward<T>(a);
因此,您正在将
a
强制转换为右值引用,并且右值具有移动语义,因此您可以看到正在调用移动构造函数。在这里,您基本上得到了
std::move

的行为:

template<typename T>
void print(T& a)
{
    cout << "val\n";
    my_obj temp = forward<T>(a);
}
模板
作废打印(T&a)
{
不能在这里:

template<typename T>
void print(T& a)
{
    cout << "val\n";
    my_obj temp = forward<T>(a);
}
模板
作废打印(T&a)
{

@pyjg没有理由感到愚蠢。每个人都必须在某个时候学会这一点。因此,正确的修复方法应该是在该函数中使用
my_obj temp=a;
。@pyjg是的。转发的目的是保留值类别,但这里我们知道我们有一个左值。通常,你只想
转发
转发引用,而你没有一,所以不要转发(正确的转发应该是转发(a)
,但请不要写)。明白了,谢谢你的解释。它现在很有意义:)@pyjg没有理由感到愚蠢。每个人都必须在某个时候学习这一点。所以正确的修复方法是在该函数中使用
my_obj temp=a;
。@pyjg是的。转发的目的是保留值类别,但这里我们知道我们有一个左值。通常,你只想
forward
forwarding references-你没有,所以不要
forward
(“正确”的转发应该是
forward(a)
,但请不要真的写)。明白了,谢谢你的解释,现在很有意义:)