zoukankan      html  css  js  c++  java
  • 容器中的对象拷贝

    《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

    只构造了一次对象,并且可以正常释放了。

  • 相关阅读:
    ZXing 生成、解析二维码图片的小示例
    OpenLDAP 2.4.x源码安装配置
    Elasticsearch & Kibana with Shield
    Kibana SSL
    Kibana 官方示例
    ELK 处理分析日志(nginx,syslog)
    Elasticsearch 负载均衡集群
    Elasticsearch REST API小记
    ELK 安装配置
    ELK 安装配置
  • 原文地址:https://www.cnblogs.com/jingyg/p/5424606.html
Copyright © 2011-2022 走看看