本文主要介绍 C++ 中使用容器和拥有指针作为属性的类容易遇到的问题,以及 C++11 新的解决思路
在 C++03 中使用带指针属性的类
假如我们定义了这样一个类
1 | class Person { |
我们希望把这个类放到 vector
里面,于是写出了一段看上去似乎没问题,但事实上会崩溃的代码
1 | int main() { |
为了避免这个问题,在 C++03 中,常见的解决方法是给 Person 添加一个拷贝构造函数
1 | Person(const Person& rhs) {pName = new string(*rhs.pName);} |
然而,使用这种方法时,”Bob” 被多余地构造和释放了一次,造成了浪费
C++11 的解决方法
C++11 中,解决这个问题最简单的方法是,使用 emplace_back
替换 push_back
,让容器自己来构造对象
1 | int main() { |
C++11 中,各种容器的插入,都实现了 emplace 版本
然而,如果我们一定要使用 push_back
,注意到 Person("Bob")
是个右值,由于 C++11 重载了右值版本的 push_back(T&&)
,我们给 Person
添加移动构造函数
1 | Person(Person&& rhs) {pName = rhs.pName; rhs.pName = nullptr;} |
这样,push_back
内部只会发生两次指针赋值操作,而不是重新构造一个字符串
那么,使用智能指针能不能解决这个问题呢?答案是可以的,两种解决方法
1 | // 1. 使用 shared_ptr |
要注意的是, 如果使用 shared_ptr
,每次拷贝之后 pName
指向的字符串事实上是共享的;如果使用 unique_ptr
,则 Person
是不可拷贝只可移动的