Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 无法理解为什么完美转发不起作用_C++_Templates_C++11_Perfect Forwarding - Fatal编程技术网

C++ 无法理解为什么完美转发不起作用

C++ 无法理解为什么完美转发不起作用,c++,templates,c++11,perfect-forwarding,C++,Templates,C++11,Perfect Forwarding,我试图理解完美转发是如何工作的,但我无法理解为什么在下面的代码中调用复制构造函数 #include <utility> #include <iostream> using std::cout; using std::endl; class Something { public: Something() = default; Something(__attribute__((unused)) const Something& other) {

我试图理解完美转发是如何工作的,但我无法理解为什么在下面的代码中调用复制构造函数

#include <utility>
#include <iostream>
using std::cout;
using std::endl;

class Something {
public:
    Something() = default;
    Something(__attribute__((unused)) const Something& other) {
        cout << "Copy constructor called" << endl;
    }
    Something(__attribute__((unused)) Something&& other) {
        cout << "Move constructor called" << endl;
    }

    void print() {
        cout << "Something::print() called" << endl;
    }
};

void function_1(Something&& one) {
    cout << "version two called" << endl;
    Something inner{one};
    inner.print();
}
void function_1(const Something& one) {
    Something inner(one);
    inner.print();
}

template <typename... T>
void test_function(T&&... ts) {
    function_1(std::forward<T>(ts)...);
}

int main() {

    const Something some1 {Something()};

    test_function(some1);
    test_function(Something());

    return 0;
}
将代码更改为在右值参考中包含
std::move
,这是可行的,但我没想到会需要它。当引用是右值引用时,应该自动调用正确的构造函数,对吗?解析了正确的引用,但调用了错误的构造函数。任何帮助都将不胜感激

右值引用绑定到右值。它本身不是右值,因为它有一个名称

但任何在使用点有名称的东西在默认情况下都是左值,即使是右值引用。您的代码可以使用
某物&&one
三次,如果第一次使用隐式
move
s,您将被拧死

相反,它在使用点是一个左值(默认情况下),并绑定到一个右值

当您想要发出信号表示不再需要其状态保持时,
std::move
it

通过将
std::forward(blah)
放在您希望从blah移动的位置(如果它是右值引用),完美转发可用于编写两个
函数


现在上面充满了谎言,因为有xvalue,prvalue,lvalues等等——标准更复杂。例如,在return语句中使用变量可以将命名值转换为右值。但基本的经验法则是值得了解的:它有一个名称,它是一个左值(除非显式强制转换或过期)。

右值引用绑定到右值。它本身不是右值,因为它有一个名称

但任何在使用点有名称的东西在默认情况下都是左值,即使是右值引用。您的代码可以使用
某物&&one
三次,如果第一次使用隐式
move
s,您将被拧死

相反,它在使用点是一个左值(默认情况下),并绑定到一个右值

当您想要发出信号表示不再需要其状态保持时,
std::move
it

通过将
std::forward(blah)
放在您希望从blah移动的位置(如果它是右值引用),完美转发可用于编写两个
函数



现在上面充满了谎言,因为有xvalue,prvalue,lvalues等等——标准更复杂。例如,在return语句中使用变量可以将命名值转换为右值。但是基本的经验法则是值得了解的:它有一个名称,它是一个左值(除非显式强制转换或过期)。

此代码将调用复制构造函数,而不是移动构造函数

void function_1(Something&& one) {
    cout << "version two called" << endl;
    Something inner{one};
    inner.print();
}
void function_1(Something&& one) {
    cout << "version two called" << endl;
    Something inner{std::move(one)};
    inner.print();
}

可以是右值,并且可以调用move而不使用
std::move

此代码将调用copy-ctor,而不是move-ctor

void function_1(Something&& one) {
    cout << "version two called" << endl;
    Something inner{one};
    inner.print();
}
void function_1(Something&& one) {
    cout << "version two called" << endl;
    Something inner{std::move(one)};
    inner.print();
}

可以是右值,并且可以调用move而不使用
std::move

这应该很容易理解:只需在构造函数上设置一个断点,当您点击它时,回溯将告诉您如何调用它。这是使用调试器可以解决的最简单的问题之一。@SamVarshavchik我知道如何调用它,但是调用了错误的重载!你怎么说?您确实知道需要显式使用std::move()来保留右值引用语义,对吗?@SamVarshavchik不是当它是右值引用时?这会使移动构造方式一直太显式,当您真正传递右值时,它不是显式的。但是,在这里,它不是右值。它是一个右值引用。右值!=右值引用。查找std::forward的功能。它对右值引用的专门化显式使用std::move()。这应该很容易理解:只需在构造函数上设置一个断点,当您点击它时,回溯将告诉您如何调用它。这是使用调试器可以解决的最简单的问题之一。@SamVarshavchik我知道如何调用它,但是调用了错误的重载!你怎么说?您确实知道需要显式使用std::move()来保留右值引用语义,对吗?@SamVarshavchik不是当它是右值引用时?这会使移动构造方式一直太显式,当您真正传递右值时,它不是显式的。但是,在这里,它不是右值。它是一个右值引用。右值!=右值引用。查找std::forward的功能。它对右值引用的专门化显式使用std::move()。但是为什么要调用复制构造函数呢?我不认为我完全理解到底发生了什么
one
是一个右值。那么为什么不调用右值构造函数呢?现在发生的是,
test\u函数(Something())
导致
versiontwo调用了
行。(在
函数1(Something&&)
实现的第一行)。然后复制发生。在
内部某物{one}。在
test\u函数(Something())
中,它正确地匹配了作为r值引用的函数,否则您将看不到名为
版本2。只有当
internal
被实例化时,您才能获得副本。我想将两个答案都标记为正确,但遗憾的是我无法做到这一点。我会投票给你的答案,给你同等的积分奖励!但是为什么要调用复制构造函数呢?我不认为我完全理解到底发生了什么
one
是一个右值。那么为什么不调用右值构造函数呢?现在发生的是,
test\u函数(Something())
导致
versiontwo调用了
行。(在
函数1(Something&&)
实现的第一行)。然后复制发生。在
内部某物{one}。在
test\u函数(Something())
中,它正确地匹配了作为r值引用的函数,否则您将看不到名为
版本2。