容器中的对象拷贝
《Effective STL》第3条
当往容器中保存对象时,保存的并不是提供给容器的那些对象,而是那些对象的拷贝。
如何拷贝?利用的是对象的拷贝构造函数。
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 class Foo 6 { 7 public: 8 Foo(int x):_x(x)
9 { 10 cout << "constructor" << endl; 11 } 12 ~Foo() 13 { 14 cout << "destructor" << endl; 15 } 16 17 private: 18 int _x; 19 }; 20 21 int main() 22 { 23 vector<Foo> vec; 24 Foo f(1); 25 vec.push_back(f); 26 return 0; 27 }
成功执行,输出
constructor
destructor
destructor
编译会帮忙生成拷贝构造函数
如果禁用拷贝构造函数
#include <iostream> #include <vector> using namespace std; class Foo { public: Foo(int x):_x(x) { cout << "constructor" << endl; } ~Foo() { cout << "destructor" << endl; } Foo (const Foo&) = delete; private: int _x; }; int main() { vector<Foo> vec; Foo f(1); vec.push_back(f); return 0; }
编译时会报错
/usr/include/c++/4.7/bits/stl_construct.h:77:7: error: use of deleted function ?.oo::Foo(const Foo&)?
如果自己定义了拷贝构造函数
#include <iostream> #include <vector> using namespace std; class Foo { public: Foo(int x):_x(x) { cout << "constructor" << endl; } ~Foo() { cout << "destructor" << endl; } Foo (const Foo& f) { cout << "copy constructor" << endl; _x = f._x; } private: int _x; }; int main() { vector<Foo> vec; Foo f(1); vec.push_back(f); return 0; }
执行输出:
constructor
copy constructor
destructor
destructor
执行了自己定义的拷贝构造函数
对于内置类型来说,总是简单的按位拷贝。
结论:由于容器会创建拷贝,所以如果一个对象的拷贝很费时,那就有可能成为性能瓶颈。
如何提高性能?
避免拷贝
使用指针
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 class Foo 6 { 7 public: 8 Foo(int x):_x(x) 9 { 10 cout << "constructor" << endl; 11 } 12 ~Foo() 13 { 14 cout << "destructor" << endl; 15 } 16 17 Foo (const Foo& f) 18 { 19 cout << "copy constructor" << endl; 20 _x = f._x; 21 } 22 private: 23 int _x; 24 }; 25 26 int main() 27 { 28 vector<Foo*> vec; 29 Foo* f = new Foo(1); 30 vec.push_back(f); 31 return 0; 32 }
输出
constructor
这里有个问题,new 的指针没有释放,容器对象在析构时,不能自动释放成员指针指向的内存。
必须自己释放
1 int main() 2 { 3 vector<Foo*> vec; 4 Foo* f = new Foo(1); 5 vec.push_back(f); 6 delete f; 7 return 0; 8 }
有点麻烦,现在可以考虑使用智能指针了
1 #include <iostream> 2 #include <memory> 3 #include <vector> 4 using namespace std; 5 6 class Foo 7 { 8 public: 9 Foo(int x):_x(x) 10 { 11 cout << "constructor" << endl; 12 } 13 ~Foo() 14 { 15 cout << "destructor" << endl; 16 } 17 18 Foo (const Foo& f) 19 { 20 cout << "copy constructor" << endl; 21 _x = f._x; 22 } 23 private: 24 int _x; 25 }; 26 27 int main() 28 { 29 vector<shared_ptr<Foo>> vec; 30 shared_ptr<Foo> f = make_shared<Foo>(1); 31 vec.push_back(f); 32 return 0; 33 }
执行输出
constructor
destructor
只构造了一次对象,并且可以正常释放了。