我有一个存储大型std::map
的类。我的理解是,做这件事的惯用方法是:
class Foo {
public:
Foo(/* Note: passed by value */ std::map<Bar, Baz> large_map) : large_map_(std::move(large_map)) {}
private:
std::map<Bar, Baz> large_map_;
};
int main() {
std::map<Bar, Baz> large_map;
// Work hard to initialize large_map.
Foo foo = Foo(std::move(large_map));
}
这将large_map的所有权从main转移到构造函数arg,然后转移到Foo的成员。这个问题是代码很难正确使用,我发现有人在某个地方创建了一个Foo
,却忘记了将映射移动到ctor:中
void deep_dark_hidden_code() {
std::map<Bar, Baz> large_map;
// Work hard to initialize large_map.
Foo foo = Foo(large_map); // Whoops! The author of this code forgot to std::move
}
我正在寻找一种写Foo
的方法,以防止此类错误。我的第一个想法是使用unique_ptr
class Foo {
public:
Foo(std::unique_ptr<std::map<Bar, Baz>> large_map_ptr) : large_map_(std::move(*large_map_ptr)) {}
private:
std::map<Bar, Baz> large_map_;
};
int main() {
std::unique_ptr<std::map<Bar, Baz>> large_map_ptr = new std::map<Bar, Baz>;
// Work hard to initialize large_map_ptr.
Foo foo = Foo(std::move(large_map_ptr));
}
该代码本质上是使用unique_ptr
作为破解来擦除std::map
的复制构造函数。我的问题是,是否有更明确的方法来做到这一点。一些神奇的模板make_uncopyable
,如:
class Foo {
public:
Foo(make_uncopyable<std::map<Bar, Baz>> large_map) : large_map_(std::move(large_map)) {}
private:
std::map<Bar, Baz> large_map_;
};
所需的效果是保持main
中的代码不变,但阻止deep_dark_hidden_code
中的代码编译。
这里的标题似乎有点用词不当(或者至少与您的问题内容不一致(:
(至少在给定的示例中(,您不希望删除复制构造函数,即Foo::Foo(const Foo& other)
,而是使用不可移动的参数来阻止调用Foo
的构造函数。
正如Mestkon所指出的(这都归功于他们——如果他们想把它作为答案发布,只要喊我一声,我就会删除我的(,你可以更改Foo
的构造函数,使其需要std::map<Bar, Baz>&& large_map
,即
Foo(std::map<Bar, Baz>&& large_map) : large_map_(std::move(large_map)) {}
Godbolt的测试确认编译器将拒绝接受deep_dark_hidden_code().
中的Foo foo = Foo(large_map);
,要求参数是可移动的(根据需要(。这可能仍然会冒着其他人的风险;"固定";他们的代码通过简单地在他们的CCD_ 17周围拍打CCD_ 16。。。然后尝试在用它构建CCD_ 18之后继续使用它
如果您想要真的想要阻止调用复制构造函数(此处为std::map
(,事情会变得相当困难,因为您无法更改定义std::map来擦除其复制构造函数。我觉得我没有一个好的答案。