一个警告引发的思考
在c++11之前,无论是effective系列还是c++教程,都会告诉我们在一定情况下使用const &来节省性能。但是在c++11之后,有了移动语义,使一些不可能的行为变成了可能。我们先来看一段简单的代码。
class Person {
private:
unsigned m_age = 0;
string m_name;
Person(const string & name) : m_name(name) { }
}
clang-tidy会给出这样的一个警告。
Clang-Tidy: Pass by value and use std::move
为什么会这样呢,这无疑是一个正确的构造函数,但是为什么还要给我们这样的警告呢?
使用值传递加移动语义避免不必要的消耗
我们按照警告更改成后是这样
Person(string name) : m_name(std::move(name)) { }
你可能会感到疑惑?为什么使用了值传递还会有更高的性能呢?这似乎和直觉不符。
慢慢来,我们一点点分析。
假设调用构造函数传递的是一个左值,那么好,string会进行copy一次,然后再进行一次移动构造。
假设调用构造函数传递的是一个右值,string会进行一次右值版本的构造,也就是一次移动构造,然后再进行一次移动构造。
第一种情况:一次拷贝构造 + 一次移动构造
第二种情况:两次移动构造
而如果我们还是使用const & 的方式来进行拷贝构造,无论如何,都需要
拷贝指针一次(引用)+ 一次拷贝构造
很明显,pass by value and use std::move的情况平均下来应当是好于pass by const reference and use copy constructor
作者思考:
pass by value and use std::move 这样的改变,在大部分的情况下是无关痛痒的。大部分情况下,你可以听从clang-tidy的建议,但是不用为了追求移动而移动,不用为了高级而高级。简单胜于繁琐,简洁胜于冗杂。