我正在调整在 cppcon 2016 中谈到的延迟 ptr Herb Sutter 的想法,以便能够以更安全的方式管理由 id 表示的外部资源。
因此,我创建了一个不可复制且只能移动的类,该类持有id
该资源应表示的内容。如果对象被移动到另一个对象,就像应该成为unique_ptr
的那样。id
0
据我了解,如果被调用的函数没有任何先决条件,即使在被移动之后,您仍然应该被允许使用该对象,所以据我了解,这应该是有效的:
int main() {
resource src = make_resource(10);
resource dst;
std::cout << "src " << src.get() << std::endl;
std::cout << "dst " << dst.get() << std::endl;
dst = std::move(src);
std::cout << "src " << src.get() << std::endl; // (*)
std::cout << "dst " << dst.get() << std::endl;
src = make_resource(40);
std::cout << "src " << src.get() << std::endl;
std::cout << "dst " << dst.get() << std::endl;
return 0;
}
但是clang-tidy
给我这个警告:
警告:“src”在移动后使用 [bugprone-use-after-move]
对于src.get()
之后dst = std::move(src)
(上面标记)。
所以我的问题是:
src.get()
之后我可以打电话吗std::move(src)
- 我可以
src.get()
假设0
在std::move
. - 如果1.和2. 有效,那么有没有办法更改代码,以便 clan-tidy 知道这是有效的。如果没有,是否有办法更改有效的代码?
这是该类的实现:
struct resource {
resource() = default;
// no two objects are allowed to have the same id (prevent double free, only 0 is allowed multiple times as it represents nullptr)
resource(const resource&) = delete;
resource& operator=(const resource& other) = delete;
// set the id of the object we move from back to 0 (prevent double free)
resource(resource&& other) noexcept : id(std::exchange(other.id, 0)) {}
resource& operator=(resource&& other) noexcept {
id = std::exchange(other.id, 0);
return *this;
}
// will free the external resource if id not 0
~resource() = default;
// returns the id representing the external resource
int get() const noexcept { return id; }
protected:
// only allow the make function to call the constructor with an id
friend resource make_resource(int id);
explicit resource(int id) : id(id) {}
protected:
int id = 0; // 0 = no resource referenced
};
// in the final version the id should be retrieved by from the external ip
resource make_resource(int id) { return std::move(resource(id)); }