modernize-pass-by-value¶
随着移动语义的加入,以及标准库通过为许多类型添加移动构造函数而更新,直接按值传递参数(而不是按常量引用传递,然后复制)变得更加有趣。此检查允许编译器负责选择最佳的构造方式。
当调用代码传递一个 *右值* 并假设移动构造是一个廉价操作时,这种转换通常是有益的。以下简短的例子说明了值的构造是如何发生的
void foo(std::string s);
std::string get_str();
void f(const std::string &str) {
foo(str); // lvalue -> copy construction
foo(get_str()); // prvalue -> move construction
}
注意
目前,只有构造函数被转换为使用按值传递。欢迎为其他情况提供贡献!
构造函数中的按值传递¶
替换使用按常量引用传递的构造函数参数,这些参数被复制到类字段中。然后使用 `std::move()` 移动参数。
由于 `std::move()` 是在 `
#include <string>
class Foo {
public:
- Foo(const std::string &Copied, const std::string &ReadOnly)
- : Copied(Copied), ReadOnly(ReadOnly)
+ Foo(std::string Copied, const std::string &ReadOnly)
+ : Copied(std::move(Copied)), ReadOnly(ReadOnly)
{}
private:
std::string Copied;
const std::string &ReadOnly;
};
std::string get_cwd();
void f(const std::string &Path) {
// The parameter corresponding to 'get_cwd()' is move-constructed. By
// using pass-by-value in the Foo constructor we managed to avoid a
// copy-construction.
Foo foo(get_cwd(), Path);
}
如果参数被使用多次,则不执行转换,因为移动的对象具有未定义的状态。这意味着以下代码将保持不变
#include <string>
void pass(const std::string &S);
struct Foo {
Foo(const std::string &S) : Str(S) {
pass(S);
}
std::string Str;
};
已知限制¶
生成的代码可能出现错误的一种情况是,引用对象在初始化列表中通过“隐藏”引用被修改,然后赋值。
示例
std::string s("foo");
struct Base {
Base() {
s = "bar";
}
};
struct Derived : Base {
- Derived(const std::string &S) : Field(S)
+ Derived(std::string S) : Field(std::move(S))
{ }
std::string Field;
};
void f() {
- Derived d(s); // d.Field holds "bar"
+ Derived d(s); // d.Field holds "foo"
}
有关延迟模板解析的说明¶
当启用延迟模板解析时,模板化上下文中的一部分构造函数;模板化构造函数、类模板中的构造函数、模板类内部类的构造函数等,不会被转换。延迟模板解析在 Windows 上默认启用,作为 Microsoft 的扩展:Clang 编译器用户手册 - Microsoft 扩展.
可以使用 `-fdelayed-template-parsing` 标志启用延迟模板解析,使用 `-fno-delayed-template-parsing` 标志禁用。
示例
template <typename T> class C {
std::string S;
public:
= // using -fdelayed-template-parsing (default on Windows)
= C(const std::string &S) : S(S) {}
+ // using -fno-delayed-template-parsing (default on non-Windows systems)
+ C(std::string S) : S(std::move(S)) {}
};
另见
有关按值传递习语的更多信息,请阅读:想要速度?按值传递.
选项¶
- IncludeStyle¶
一个字符串,指定使用哪种包含风格,`llvm` 或 `google`。默认值为 `llvm`。
- ValuesOnly¶
当为 `true` 时,检查仅警告已经按值传递的已复制参数。默认值为 `false`。