为什么右值引用成员是常量?
Why rvalue reference member would be const?
我正在尝试为结构编写一个移动构造函数,但我不明白为什么我无法调用结构成员的移动构造函数:
#include <memory>
struct C
{
std::unique_ptr<int[]> mVector;
size_t mSize;
C() = default;
C(C &&temp)
: mVector(temp.mVector)
, mSize(temp.mSize)
{}
};
当我编译这个时,我得到:
gcc -c TempTest.cpp
TempTest.cpp: In constructor 'C::C(C&&)':
TempTest.cpp:9:23: error: use of deleted function 'std::unique_ptr<_Tp [], _Dp>::unique_ptr(const std::unique_ptr<_Tp [], _Dp>&) [with _Tp = int; _Dp = std::default_delete<int []>]'
9 | , mSize(temp.mSize)
| ^
In file included from c:/msys64/mingw64/include/c++/10.3.0/memory:83,
from TempTest.cpp:1:
c:/msys64/mingw64/include/c++/10.3.0/bits/unique_ptr.h:723:7: note: declared here
723 | unique_ptr(const unique_ptr&) = delete;
| ^~~~~~~~~~
因为在构造函数中 temp
是一个右值引用,它是非常量所以 temp.mVector
应该是非常量并且应该调用 unique_ptr
移动构造函数但是它调用了被删除的复制构造函数。知道错误在哪里吗?
Why rvalue reference member would be const?
不要假设它是 const
。您应该假定 unique_ptr(const unique_ptr&)
只是可用构造函数中的 最佳匹配项 。
Because in constructor temp
is a rvalue reference
惊喜!它不是 r 值参考。
当调用构造函数时,变量 temp
绑定 到右值。现在它是一个命名变量,它不再是“临时变量”。变成了左值。
因为您知道调用构造函数时值 是 右值,您可以安全地移动成员,将它们转换回右值。
C(C &&temp)
: mVector(std::move(temp.mVector))
// ^^^^^^^^^ We know that temp CAME FROM an r-value,
// so it can safely be moved.
, mSize(temp.mSize)
{}
尝试运行以下代码,一切都会变得清晰:
struct Test
{
Test(){}
Test(const Test& r)
{
std::cout << "i am using the copy constructor :) " << std::endl;
}
Test(Test&& r)
{
std::cout << "I require std::move to be selected as possible overload.." << std::endl;
}
};
int main()
{
Test first;
Test second(first);
Test third(std::move(second));
return 0;
}
std::move 通过将右值引用 (Test&&) 传递给构造函数来帮助 select 正确的构造函数重载。
在您的情况下,即使您的向量不是 const,编译器也会 selecting 复制构造函数,只是因为它被认为是最佳匹配(隐式转换为 const 引用优于隐式转换为 r -value 引用,因为第二个与第一个不同,可能会修改值)添加 std::move 您可以 select 正确的构造函数并解决您的问题。
#include <memory>
struct C
{
std::unique_ptr<int[]> mVector;
size_t mSize;
C() = default;
C(C &&temp)
: mVector(std::move(temp.mVector))
, mSize(temp.mSize)
{}
};
我正在尝试为结构编写一个移动构造函数,但我不明白为什么我无法调用结构成员的移动构造函数:
#include <memory>
struct C
{
std::unique_ptr<int[]> mVector;
size_t mSize;
C() = default;
C(C &&temp)
: mVector(temp.mVector)
, mSize(temp.mSize)
{}
};
当我编译这个时,我得到:
gcc -c TempTest.cpp
TempTest.cpp: In constructor 'C::C(C&&)':
TempTest.cpp:9:23: error: use of deleted function 'std::unique_ptr<_Tp [], _Dp>::unique_ptr(const std::unique_ptr<_Tp [], _Dp>&) [with _Tp = int; _Dp = std::default_delete<int []>]'
9 | , mSize(temp.mSize)
| ^
In file included from c:/msys64/mingw64/include/c++/10.3.0/memory:83,
from TempTest.cpp:1:
c:/msys64/mingw64/include/c++/10.3.0/bits/unique_ptr.h:723:7: note: declared here
723 | unique_ptr(const unique_ptr&) = delete;
| ^~~~~~~~~~
因为在构造函数中 temp
是一个右值引用,它是非常量所以 temp.mVector
应该是非常量并且应该调用 unique_ptr
移动构造函数但是它调用了被删除的复制构造函数。知道错误在哪里吗?
Why rvalue reference member would be const?
不要假设它是 const
。您应该假定 unique_ptr(const unique_ptr&)
只是可用构造函数中的 最佳匹配项 。
Because in constructor
temp
is a rvalue reference
惊喜!它不是 r 值参考。
当调用构造函数时,变量 temp
绑定 到右值。现在它是一个命名变量,它不再是“临时变量”。变成了左值。
因为您知道调用构造函数时值 是 右值,您可以安全地移动成员,将它们转换回右值。
C(C &&temp)
: mVector(std::move(temp.mVector))
// ^^^^^^^^^ We know that temp CAME FROM an r-value,
// so it can safely be moved.
, mSize(temp.mSize)
{}
尝试运行以下代码,一切都会变得清晰:
struct Test
{
Test(){}
Test(const Test& r)
{
std::cout << "i am using the copy constructor :) " << std::endl;
}
Test(Test&& r)
{
std::cout << "I require std::move to be selected as possible overload.." << std::endl;
}
};
int main()
{
Test first;
Test second(first);
Test third(std::move(second));
return 0;
}
std::move 通过将右值引用 (Test&&) 传递给构造函数来帮助 select 正确的构造函数重载。 在您的情况下,即使您的向量不是 const,编译器也会 selecting 复制构造函数,只是因为它被认为是最佳匹配(隐式转换为 const 引用优于隐式转换为 r -value 引用,因为第二个与第一个不同,可能会修改值)添加 std::move 您可以 select 正确的构造函数并解决您的问题。
#include <memory>
struct C
{
std::unique_ptr<int[]> mVector;
size_t mSize;
C() = default;
C(C &&temp)
: mVector(std::move(temp.mVector))
, mSize(temp.mSize)
{}
};