"used after it was moved [bugprone-use-after-move]"警告在这里是一个真正的问题吗?
Is the "used after it was moved [bugprone-use-after-move]" warning a real problem here?
我正在调整Herb Sutter在2016年cppcon中谈到的deffered ptr的想法,以便能够以更安全的方式管理由id表示的外部资源。
因此,我创建了一个不可复制且只能移动的类,该类包含资源应该表示的id
。与unique_ptr
一样,如果对象移动到另一个对象,则id
应变为0
。
根据我的理解,即使在被调用的函数没有任何先决条件的情况下,即使在移动了is之后,你仍然应该被允许使用该对象,所以根据我的了解,这应该是有效的:
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"在移动后使用[移动后使用容易出错]
对于dst = std::move(src)
之后的src.get()
(上面标记)。
所以我的问题是:
- 是否允许我在
std::move(src)
之后调用src.get()
- 我可以假设
src.get()
在std::move
之后返回0
- 如果1.和2.有效,那么有没有办法更改代码,让部落整洁知道这是有效的。如果没有,有没有办法改变代码的有效性
下面是类的实现:
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)); }
- 是否允许在std::move(src)之后调用src.get()
如果我们对src
的类型仍然不可知,那么我们就不知道了。可能不会。在某些情况下,在移动后调用成员函数是未定义的。例如,调用智能指针的间接运算符。
给定decltype(src)
的定义及其成员函数,我们知道:是的,您可以。
- 我可以假设src.get()在std::move之后返回0吗
如果我们对src
的类型保持不可知论,那么我们就对src.get()
的作用一无所知。更具体地说,我们不知道它的先决条件。
给定decltype(src)
的定义及其成员函数:是的,我们可以做出假设。
- 如果1。和2。如果是有效的,那么有没有一种方法可以更改代码,让clanicity知道这是有效的。如果没有,有没有办法改变代码的有效性
Clang整洁假设"不处于移出状态"是所有成员函数(除赋值之外)的先决条件,在这种假设下,警告违反了这种假定的先决前提。因此,它试图强制执行一个约定,始终假设这样的预条件,即使您碰巧知道它不存在于您的类中。
您可以在移动和重新分配src
之间删除对src.get()
的调用。clang整洁不会抱怨的对moved-from变量的一个操作是重新赋值,在赋值之后,对象的状态应该(传统上)得到很好的定义,并且调用其他成员函数被认为是可以的(当然,你可以有其他必须满足的先决条件,但clang整洁可能不知道)虽然从技术上讲,可以定义一种类型,即使在移动后的分配也没有很好地定义,但这种类型是非常非常规和不安全的
总之,您可以在移动后(甚至在重新分配之前)为该特定类调用src.get()
,但这样您就不会遵循clang整洁试图强制执行的约定。
cppreference.com有这样的文本:
除非另有说明,否则所有具有已从中移动,处于有效但未指定的状态。也就是说,只有没有先决条件的函数,例如赋值操作员,可以在物体从移动后安全地使用
因此,非正式地说,C++约定是从对象中移出的对象是有效的,但没有用,这就是为什么clang整洁表示使用它是可疑的。
对于您的实施,您提供了"更多"而非常规–所以你的代码没有错,只是非常规的。
- 在决定是通过参考还是通过价值时,尺寸真的是一个问题吗
- 在用于格式4的arm模拟器中实现功能时的一个问题
- 为什么在分配给成员变量之前获取unique_ptr的返回是一个问题?
- 我在使用 boost::serialization 时遇到了一个问题,我的代码在 Linux 中运行良好,但在 Wind
- 在C++,重复申报仍然是一个问题吗?
- "Memory Fragmentation"这仍然是一个问题?
- 缺少类型说明符和另一个问题
- 在浮点精度成为一个问题之前,可以将多少个浮点值加在一起
- 关于使用C++结构的一个问题
- 关于骰子概率计算的一个C++问题
- 我想知道我将如何实现 + 运算符重载.我已经从我上一个问题中计算出 += 运算符重载
- 组合理论的一个问题
- 我有一个问题,创建了C 中阻塞队列的向量
- CreateFileWindows XP和7中存在一个问题
- 我是编码新手,我面临一个问题
- 在添加新记录和访问记录时有一个问题
- 专用纯虚拟模板函数(未定义引用)的另一个问题
- 在C++中,这个Eigen::张量的声明是安全的,还是有缺陷的?我应该为它提交一个问题吗
- 我如何让我的部分代码循环并重复一个问题,直到答案是有效的输入C++
- 我的程序停止工作,因为检测到一个问题