C++ std::未调用函数移动构造函数
考虑以下代码:C++ std::未调用函数移动构造函数,c++,c++11,constructor,C++,C++11,Constructor,考虑以下代码: void makeNew(std::function<void()>&& func) { std::function<void()> p = func; } void test(){} 预期结果: 临时std::function从std::bind(test) 然后这个临时std::function对象作为右值引用传递给makeNew,然后在std::function p=func时调用move构造函数;被调用 实际发生的情况(
void makeNew(std::function<void()>&& func)
{
std::function<void()> p = func;
}
void test(){}
预期结果:
临时std::function
从std::bind(test)
然后这个临时std::function对象作为右值引用传递给makeNew,然后在std::function p=func时调用move构造函数;被调用
实际发生的情况(使用VS2010和带调试器的单步执行):
对于以下语句std::function p=func代码>,将调用复制构造函数而不是移动构造函数
有人能解释一下这种行为吗?您使用的右值引用不正确。通过右值引用获取参数不是一件很常见的事情。它没有说“我想从参数中移动”,也没有说“我想以后从这个参数中移动”。相反,它是一个引用-没有任何东西被复制或移动,它只是引用。在函数内部,表达式func
是一个左值(因为被命名的东西都是左值),因此在初始化p
时将调用复制构造函数
您应该做的是按值获取参数:
void makeNew(std::function<void()> p)
{
// ...
}
使用std::move
将表达式func
(左值)转换为右值表达式。然后,它将从。然而,我看不出有什么好的理由需要这样做,除非你进入另一个函数
当然,如果我完全错了,并且你真的想使用右值引用,那么如果你想离开它,你仍然需要执行std::move
你不正确地使用右值引用。通过右值引用获取参数不是一件很常见的事情。它没有说“我想从参数中移动”,也没有说“我想以后从这个参数中移动”。相反,它是一个引用-没有任何东西被复制或移动,它只是引用。在函数内部,表达式func
是一个左值(因为被命名的东西都是左值),因此在初始化p
时将调用复制构造函数
您应该做的是按值获取参数:
void makeNew(std::function<void()> p)
{
// ...
}
使用std::move
将表达式func
(左值)转换为右值表达式。然后,它将从。然而,我看不出有什么好的理由需要这样做,除非你进入另一个函数
当然,如果我完全错了,你真的想得到一个右值引用,如果你想离开它,你仍然需要做std::move
右值引用不是右值(从函数返回时除外)。它只是一种不同类型的左值,具有与普通引用不同的绑定规则
如果要从右值引用移动,请使用与任何其他引用相同的std::move
std::move
返回一个右值引用类型,因此表达式std::move(func)
是一个xvalue,因此它是一个右值,可以从中移动func
是左值,即使它具有右值引用类型
注意,很少需要一个接受右值引用的函数。这样做是为了排除左值,或者是因为你想阻止它们被传入,或者是因为你有一个左值重载,它做了一些不同的事情。最常见的情况是希望函数从右值移动或复制左值。因此,您可以按值获取参数并从中移动(如Joseph的回答中所示),与编写两个不同函数相比,几乎没有开销。右值引用不是右值(从函数返回时除外)。它只是一种不同类型的左值,具有与普通引用不同的绑定规则
如果要从右值引用移动,请使用与任何其他引用相同的std::move
std::move
返回一个右值引用类型,因此表达式std::move(func)
是一个xvalue,因此它是一个右值,可以从中移动func
是左值,即使它具有右值引用类型
注意,很少需要一个接受右值引用的函数。这样做是为了排除左值,或者是因为你想阻止它们被传入,或者是因为你有一个左值重载,它做了一些不同的事情。最常见的情况是希望函数从右值移动或复制左值。因此,您可以按值获取参数并从中移动(如Joseph的回答中所示),与编写两个不同函数相比,几乎没有开销。func
i为左值。您可以使用std::move将其转换为右值,右值可以从.func
i移动为左值。您可以使用std::move将其转换为右值,右值可以从中移动。std::move不是强制转换为&&@JobNick吗?右值引用类型变量的名称是左值。返回右值引用的函数是右值。std::move
所依赖的就是这个小怪癖。std::move不就是强制转换到&&@JobNick吗?右值引用类型变量的名称是左值。返回右值引用的函数是右值。这就是std::move
所依赖的这个小怪癖。
void makeNew(std::function<void()> func)
{
std::function<void()> p = std::move(func);
}