在使用STL容器时避免使用具有复杂拷贝构造函数的类

来源:互联网 发布:mac怎么映射键盘 编辑:程序博客网 时间:2024/05/17 06:23

  在使用STL容器时避免使用具有复杂拷贝构造函数的类。在向STL容器插入一个对象时,容器类会调用插入类的拷贝构造函数,如果插入类的拷贝构造函数很复杂,则将直接影响效率。

  那么何谓复杂呢?比如,进行大量内存的拷贝,大量耗时的运算,等等,其实质就是需要做很多工作,需使用很多资源!如下例子说明了,即使CTest类定义了从int类型变量构造的方法,但同样在STL容器中调用拷贝构造函数。

  1. #include <iostream>
  2. #include <deque>
  3. class CTest
  4. {
  5. //protected:
  6.     int num;
  7. public:
  8.     CTest(int i=0):num(i){std::cout<<"constructure CTest(int i=0)"<<std::endl;}
  9.     CTest(const CTest & t):num(t.num){std::cout<<"constructure CTest(const CTest & t)"<<std::endl;}
  10.     friend std::ostream & operator<<(const CTest & t,std::ostream & os);
  11.     friend std::ostream & operator<<(std::ostream & os,const CTest & t);
  12. };
  13. std::ostream & operator<<(const CTest & t,std::ostream & os)
  14. {
  15.     std::cout<<t.num;
  16.     return os;
  17. }
  18. std::ostream & operator<<(std::ostream & os,const CTest & t)
  19. {
  20.     std::cout<<t.num;
  21.     return os;
  22. }
  23. int main(int argc, char * argv[])
  24. {
  25.     std::deque<CTest> queue;
  26.     for(int i=0;i<10;++i)
  27.     {
  28.         std::cout<<"push_front "<<i<<std::endl;
  29.         queue.push_front(i);
  30.     }
  31.     for(std::deque<CTest>::const_iterator cit=queue.begin();cit!=queue.end();++cit)
  32.         std::cout<<*cit<<std::endl;
  33.     return 0;
  34. }

  但并不意味着复杂或者说重量级的类不能使用STL容器来封装。我们可以将问题转化!在插入对象到容器中时,首先创建一个“空对象”,即默认构造函数,什么也不做,拷贝构造函数,也什么都不做,插入成功后,使用赋值的方式来完成对象的复杂拷贝构造函数需要做的事情!

  上面的例子,只能用于说明在使用STL容器时的构造函数调用情况,不能说明为什么要将拷贝构造函数做成一个轻量级的函数。下面简单说明一下。

  假设CTest内部有一个大块内存空间的属性。一般情况下,拷贝构造函数都会将右值对象中的内存复制到左值对象的内存。然而,一般情况下,这个类应该还会具有这样一个构造函数CTest(char * p);(假设这大块内存是一个很大的字符串几兆甚至几十兆)。那么在使用STL容器时,我们可能会这样做(假设使用前面的代码的queue):queue.push_front(buff);这样在CTest(char *p)的构造函数会复制着一大块内存,再调用拷贝构造函数时,又会复制这块内存一次,这样会影响程序的性能,假设,需要插入很多这样的元素,那么程序肯定在性能上受到严重影响。

  解决办法:设计CTest();构造函数,什么也不做,也许只初始化内部指针为NULL;设计拷贝构造函数按照正常的情况完成代码,只不过,对于空对象,她已经不再有那么多事情要做了,例如:要复制的对象其内部内存指针为NULL,完全不需要复制大块内存;设计赋值运算符,完成内存拷贝工作:CTest & operator=(char * p);这样就会避免大量操作在两次构造函书中执行。

  使用一个默认构造函数,简化STL内部类的拷贝构造函数工作,插入到STL容器后再修改类的状态执行更为复杂的操作,这样,避免了STL内部调用拷贝构造函数造成的可能影响性能的问题。

原创粉丝点击