clang-tidy 建议我删除 const 引用,为什么?

cyp*_*ist 6 c++ c++17 clang-tidy

我在一个项目树上运行了 clang-tidy(“现代化”模块),我一直在努力使 C++17 保持合理的最新状态。它纠正的几乎所有内容对我来说都不足为奇,除了一件事:它改变了所有这些类型的结构:

void foo(const std::string& str) {
}
Run Code Online (Sandbox Code Playgroud)

..对此:

void foo(std::string str) {
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么。在我未经训练的眼睛看来,这意味着两件事:

  1. 它需要复制对象而不是仅仅传递引用。(尽管我假设在某些情况下,编译器可以推断出它在生成代码时可以只传递一个指针——但引用使其明确(恕我直言更好))。
  2. const 用于告诉函数体开发人员它不应该更改输入字符串,并且如果需要修改字符串,则需要将其自己的副本存储在某处。

不过,我确实看到了一个好处——通过将一个对象作为const引用传递,它只是一个“删除常量”,无论如何都不会被改变,所以我想通过值传递可以解决这个问题。

为什么它建议删除带有非常量传递值的常量引用?

cig*_*ien 7

这里给出的理由是

随着移动语义添加到语言和标准库更新,为许多类型添加移动构造函数,现在有趣的是直接通过值而不是通过常量引用获取参数,然后复制。此检查允许编译器负责选择构造副本的最佳方式。

此外

当调用代码传递一个右值并假设移动构造是一个廉价的操作时,转换通常是有益的。

但是,文档指出唯一的替换是在以下特定情况下:

替换复制到类字段中的 const 引用构造函数参数的使用。然后用 std::move() 移动参数。

如果构造函数参数被多次使用,它甚至不会应用转换。

所以我不认为你的所有功能都应该像那样转换。

  • 请注意,clang-tidy 很棒,但您应该始终仔细检查转换以确保它们不会破坏任何内容。最好的方法是进行大量的测试:) (2认同)
  • 哈,我知道这种感觉。但如果你有一堆测试,那就太好了;大胆一点,去做吧:) (2认同)