Fin*_*inn 5 c++ string reference move-semantics
我的类有字符串变量,我想用传递给构造函数的值来初始化它们。
我的老师认为我们将字符串作为常量引用传递:
MyClass::MyClass(const std::string &title){
this->title = title
}
Run Code Online (Sandbox Code Playgroud)
但是 Clang-Tidy 建议使用 move 命令:
MyClass::MyClass(std::string title){
this->title = std::move(title)
}
Run Code Online (Sandbox Code Playgroud)
所以我想知道在现代 C++ 中这样做的正确方法是什么。
我已经环顾四周,但没有什么能真正回答我的问题。提前致谢!
没有一个是最佳的,因为它们都title首先默认构造,然后复制分配或移动分配它。使用成员初始值设定项列表。
MyClass::MyClass(const std::string& title) : title(title) {} // #1
// or
MyClass::MyClass(std::string title) : title(std::move(title)) {} // #2
//or
MyClass::MyClass(const std::string& title) : title(title) {} // #3
MyClass::MyClass(std::string&& title) : title(std::move(title)) {} // #3
Run Code Online (Sandbox Code Playgroud)
让我们看看它们,看看 C++17 中会发生什么:
#1 - 单个转换构造函数采用const&.
MyClass::MyClass(const std::string& title) : title(title) {}
Run Code Online (Sandbox Code Playgroud)
这将std::string通过以下方式之一创建 1 或 2 s:
std::string由转换构造函数构造std::string,然后复制构造成员。#2 - 单个转换构造函数采用std::string按值。
MyClass(std::string title) : title(std::move(title)) {}
Run Code Online (Sandbox Code Playgroud)
这将std::string通过以下方式之一创建 1 或 2 s:
str1str2std::string转换构造函数构造,然后移动构造成员。#3 - 组合两个转换构造函数。
MyClass(const std::string& title) : title(title) {}
MyClass(std::string&& title) : title(std::move(title)) {}
Run Code Online (Sandbox Code Playgroud)
这将std::string通过以下方式之一创建 1 或 2 s:
std::string由转换构造函数构造std::string,然后移动构造成员。到目前为止,选项#3似乎是最有效的选择。让我们再检查几个选项。
#4 - 与 #3 类似,但用转发构造函数替换移动转换构造函数。
MyClass(const std::string& title) : title(title) {} // A
template<typename... Args>
explicit MyClass(Args&&... args) : title(std::forward<Args>(args)...) {} // B
Run Code Online (Sandbox Code Playgroud)
这将始终std::string以下列方式之一创建 1:
A。B。std::string(可能转换的)构造函数通过构造B。#5 - 仅转发构造函数 - 从 #4 中删除复制转换构造函数。
template<typename... Args>
explicit MyClass(Args&&... args) : title(std::forward<Args>(args)...) {}
Run Code Online (Sandbox Code Playgroud)
这将始终std::string像#4 中那样创建 1,但所有操作都是通过转发构造函数完成的。
std::string。#6 - 单参数转发转换构造函数。
template<typename T>
explicit MyClass(T&& title) : title(std::forward<T>(title)) {}
Run Code Online (Sandbox Code Playgroud)
这将始终像 #4 和 #5 一样创建 1 std::string,但只会采用一个参数并将其转发给std::string构造函数。
std::string。#6如果您想在构造函数中采用多个参数,则可以轻松地使用Option来进行完美转发MyClass。假设您有一个int成员和另一个std::string成员:
template<typename T, typename U>
MyClass(int X, T&& title, U&& title2) :
x(X),
title(std::forward<T>(title)),
title2(std::forward<U>(title2))
{}
Run Code Online (Sandbox Code Playgroud)