【发布时间】:2021-01-22 20:40:01
【问题描述】:
#include<algorithm>
#include<vector>
#include<memory>
class Foo {
public:
Foo();
#if 1
// Destructor for rule of 5.
~Foo(){}
// Move constructor yes.
Foo(Foo&&) noexcept = default;
// Move assignment probably won't actually be created because const member variable.
// Do I need it though? Why would vector need to move-assign?
Foo& operator=(Foo&&) noexcept = default;
// Copy no.
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
#endif
protected:
// It works if non-const. Broken if const.
const std::unique_ptr<int> ptr;
};
int main()
{
std::vector<Foo> bar;
bar.reserve(1);
}
我收到错误(使用 GCC):
static assertion failed: result type must be constructible from value type of input range
但是为什么呢?
在我看来,默认构造函数和移动构造函数都应该没问题。这是万一吗?我 const_cast 去掉 const 并擦除中间元素,vector 可能会尝试移动分配以“碎片整理”向量? (而如果它试图破坏+移动构造,那会起作用)
在上面的片段中,unique_ptr 代表我自己的只移动类型,所以这个问题与指针无关。
【问题讨论】:
-
您希望指针 为
const还是希望它指向 的对象为const?在后一种情况下,只需:std::unique_ptr<const int> ptr; -
如果
unique_ptr是常量,则不能移动它,因为这会将其指针重置为nullptr。 -
""// 5 规则的析构函数。"对规则 5 的错误解释。“如果你实现 1,那么你需要实现所有 5”是一种简化。整个故事是这样的:如果你觉得需要写 5 个中的 1 个,那么你的班级很可能拥有并管理一个资源。如果您的班级负责手动管理资源,那么您需要实现所有 5 个。在您的情况下,您的班级不管理任何资源,因此您不需要编写析构函数。实际上建议不要写析构函数。
-
你不能移动 const 的东西。移动构造函数的默认实现将不起作用,但您可以实现自己的移动构造函数,并复制无法移动的成员并移动其他可移动的成员。
-
@TedLyngmo:就像我说的,这是一个 unique_ptr 代表实际对象的示例。这与指针无关。我知道你所说的区别。
标签: c++ vector stl move-semantics