创建通用引用的重载函数,但很多时候还是会调用到通用引用函数,这会让人很迷惑。
Effective C++ :区分通用引用和右值引用
声明一个右值引用,使用T&&
这种格式,但是这玩意并不是表面上看到的那么简单。
1
2
3
4
5
6
7void f(Widget&& param); // 右值引用
Widget&& var1 = Widget(); // 右值引用
auto&& var2 = var1; // 通用引用
template<typename T>
void f(std::vector<T>&& param); // 右值引用
template<typename T>
void f(T&& param); // 通用引用
Effective C++ :对右值引用使用 std::move,对通用引用使用 std::forward
当形参被声明为右值引用时,意味着传入的实参需要是右值引用,并且该参数是可移动的。既然目的如此明确,那么使用std::move
是正确的选择:
1
2
3
4
5
6
7
8
9
10
11class Widget {
public:
Widget(Widget&& rhs) // rhs is rvalue reference
: name(std::move(rhs.name)),
p(std::move(rhs.p))
{ … }
…
private:
std::string name;
std::shared_ptr<SomeDataStructure> p;
};std::forward
是正确的选择:
1
2
3
4
5
6
7class Widget {
public:
template<typename T>
void setName(T&& newName) // newName is
{ name = std::forward<T>(newName); } // universal reference
…
};
Effective C++ :理解 std::move 和 std::forward
需要时刻牢记的是:函数的形参都是左值,即使它的类型是右值引用,它也是左值,因为它可以被取地址。
主要是区分什么是右值,满足以下二者之一即可: 1. 临时对象 2. 无法位于赋值符号右边的对象
Effective C++ :尽可能的使用 constexpr
使用constexpr
以让编译器来检查该值是否是常量表达式,降低程序员负担。
Effective C++ :const iterators 优于 iterators
除非是需要修改容器元素的内容,否则在使用迭代器的时候,应该使用其const
版本,也就是指向const
类型元素的指针,以避免误操作。
Effective C++ :作用域枚举优于非作用域枚举
简单来讲就是对于枚举类型,也需要将其存放于命名空间中,以避免枚举中元素对外部标识符的污染。
Effective C++ :using 优于 typedef
在 c 中,typedef
是我经常使用的别名语法。但在 cpp
中,using
才是更好的选择。
Effective C++ :理解 auto
理解了 auto
的推导原则后,就需要认识到使用
auto
所带来的便利性和缺陷,才能正确的使用它。
Effective C++ :nullptr 优于 0 和 NULL
在 c 中,通常使用NULL
表示一个空指针,但是在 cpp
中有更优的nullptr
可供选择。