首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >clang(版本14)对这段代码的“易出错-使用后-移动”错误是否正确?

clang(版本14)对这段代码的“易出错-使用后-移动”错误是否正确?
EN

Stack Overflow用户
提问于 2022-09-15 10:28:20
回答 2查看 118关注 0票数 3
代码语言:javascript
运行
复制
struct test {
    test& foo(std::vector<int> const& v) {
        assert(v.size() == 1); return *this; 
    }

    void bar(std::vector<int> v) {}
};

void do_test() {
    std::vector<int> v = { 42 };
    return test{}.foo(v).bar(std::move(v)); // <-- here
}

clang在“这里”字符串上给出一个错误bugprone-use-after-move

为什么它是在移动后使用?

EN

回答 2

Stack Overflow用户

发布于 2022-09-15 11:06:38

因为C++17保证函数调用中的后缀表达式,即在这里,在参数列表中的任何表达式之前对test{}.foo(v).bar进行求值。

因此,只有在foo返回之后,移动构造才会发生。

然而,在C++17之前,没有这样的保证,移动-建设可能发生在调用foo之前。

依赖这些新的担保是否是一个好主意是值得怀疑的。有些工具倾向于忽略它们,并继续警告这些代码,因为如果使用不同的-std=标志编译,这将是危险的。例如,GCC在其-Wunsequenced警告上也是如此。另外,当C++17刚刚实现时,一些较旧的编译器版本可能仍然存在这方面的错误。

票数 4
EN

Stack Overflow用户

发布于 2022-09-15 11:02:25

在……里面

代码语言:javascript
运行
复制
foo(v).bar(std::move(v))

没有任何保证(请参阅注释,预C++17),即foo(v)中的std::move(v)将在bar(std::move(v))中的std::move(v)之前进行评估。

整洁的文档提供了一个这方面的例子。

取消顺序的移动、使用和重新初始化 在许多情况下,C++不保证计算语句的子表达式的顺序。这意味着,在如下代码中,不能保证在移动之前还是之后使用: 空f(int i,std::向量v);std::向量v={ 1,2,3 };f(v1,std::move(v)); 在这种情况下,检查会注意到使用和移动是没有顺序的。 当在与移动或使用相同的语句中重新初始化时,检查还将考虑排序规则。只有保证在移动后和使用之前重新初始化变量时,才会考虑重新初始化。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73729536

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档