c++ - 移动语义与 const 引用
问题描述
我的类有字符串变量,我想用传递给构造函数的值来初始化它们。
我的老师认为我们将字符串作为常量引用传递:
MyClass::MyClass(const std::string &title){
this->title = title
}
但是 Clang-Tidy 建议使用 move 命令:
MyClass::MyClass(std::string title){
this->title = std::move(title)
}
所以我想知道在现代 C++ 中执行此操作的正确方法是什么。
我已经环顾四周,但没有真正回答我的问题。提前致谢!
解决方案
None 是最佳的,因为它们都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
让我们看看它们,看看在 C++17 中发生了什么:
#1 - 单个转换构造函数采用const&
.
MyClass::MyClass(const std::string& title) : title(title) {}
std::string
这将通过以下方式之一创建 1 或 2秒:
- 该成员是复制构造的。
- A
std::string
由std::string
转换构造函数构造,然后成员是复制构造的。
#2 - 单个转换构造函数采用std::string
按值。
MyClass(std::string title) : title(std::move(title)) {}
std::string
这将通过以下方式之一创建 1 或 2秒:
- 参数是通过临时(+ )的返回值优化构造的,然后移动构造成员。
str1
str2
- 参数是复制构造的,然后成员是移动构造的。
- 参数是移动构造的,然后成员是移动构造的。
- 参数由
std::string
转换构造函数构造,然后成员被移动构造。
#3 - 结合两个转换构造函数。
MyClass(const std::string& title) : title(title) {}
MyClass(std::string&& title) : title(std::move(title)) {}
std::string
这将通过以下方式之一创建 1 或 2秒:
- 该成员是复制构造的。
- 该成员是移动构造的。
- A
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
这将始终std::string
以下列方式之一创建 1:
- 该成员是通过复制构造的
A
。 - 该成员是通过移动构造的
B
。 - 该成员由
std::string
(可能转换的)构造函数通过B
.
#5 - 仅转发构造函数 - 从 #4 中删除复制转换构造函数。
template<typename... Args>
explicit MyClass(Args&&... args) : title(std::forward<Args>(args)...) {}
这将始终像 #4 中一样创建 1 std::string
,但所有这些都是通过转发构造函数完成的。
- 该成员是复制构造的。
- 该成员是移动构造的。
- 该成员由
std::string
(可能转换的)构造函数构造。
#6 - 单参数转发转换构造函数。
template<typename T>
explicit MyClass(T&& title) : title(std::forward<T>(title)) {}
这将始终像 #4 和 #5 一样创建 1 std::string
,但只会采用一个参数并将其转发给std::string
构造函数。
- 该成员是复制构造的。
- 该成员是移动构造的。
- 该成员由
std::string
转换构造函数构造。
#6
如果您想在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))
{}
推荐阅读
- python - 如何在 python 的 sklearn 中使用 gridsearchcv 执行特征选择
- php - 正则表达式匹配(1 个或多个)包含空行的 php heredocs
- r - 从存储在列表中的 data.frame 调用变量
- django - 您在 Django 中创建模型的过程是什么?
- angular - 如何在这个组件中实现这个 ionic 3 无限滚动?
- python - 合并两个 2D numpy.ndarray
- xamarin.forms - 如何从 Xamarin.ios 访问 UIImagePickerController 快门 UiButton
- python - Pycharm 自动导入没有遵循最佳实践?
- java - 检查数据库中存在的大量字符串的有效方法
- javascript - 如何使用 Node.js 和 express 在 PostgreSQL 中不使用方括号换行来获取对象?