容器中的对象拷贝

《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

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

时间: 2024-08-22 11:26:05

容器中的对象拷贝的相关文章

Java 开发中的对象拷贝

前言 在 Java 开发中,很多时候需要将两个属性基本相同的对象进行属性复制,比如 DO 转 VO等等. 本文主要介绍自己实现的简易拷贝工具类与 Spring 提供的属性拷贝的对比. Spring 提供的属性拷贝 在 Spring 中直接调用 BeanUtils.copyProperties();即可. 它的核心通过循环 target 的所有方法名,然后在 source 中找到对应的方法名,最后通过反射从 source 中获取并写入 target 中. Spring 没有通过 java.lang

asp.net core不通过构造方法从容器中获取对象及解决通过这种方法NLog获取对象失败的问题

一般想从容器中获取对象,我们都是通过构造方法获取对象,但有些条件不允许不能通过构造方法获取对象,我们必须单独从容器中单独创建获取找个对象,这样我们就不行把找个容器静态保存起来供全局diaoy 一. 简单些一下步骤如下:(从某一个大神视频或者代码中学习到的,具体哪个不记得了) 1.先做一个构建对象的接口IEngine public interface IEngine { /// <summary> /// 构建一个实例 /// </summary> /// <typeparam

python中的对象拷贝

python中无论参数传递还是函数返回值,都是进行引用传递.那如何拷贝对象呢,标准库的copy模块提供了两个方法:copy和deepcopy方法. 1. copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象. 2. copy.deepcopy 深拷贝 拷贝对象及其子对象 见下例: import copy a = [1, 2, 3, 4, ['a', 'b']] #原始对象 e = a[:] #利用分片操作进行拷贝(浅拷贝) b = a <span style="white-

win 10 无法删除系统文件的解决方法(提示:无法枚举容器中的对象 访问被拒绝)

一.右击文件 选择"属性"-"安全"-"高级",如下图 二.查看哪个用户的权限是:"完全控制",我这里是"SYSTEM"用户. 三.选择顶部的 "更改-"高级"-"立即查找",然后选择管理员账户"SYSTEM" 四.勾选下面的复选框 "替换子容器和对象的所有者" 结束:完成上面的操作后就可以正常删除了. 原文地址:ht

OC中对象拷贝概念

OC中的对象拷贝概念,这个对于面向对象语言中都会有这种的问题,只是不同的语言有不同的解决方式:C++中有拷贝构造函数,Java中需要实现Cloneable接口,在clone方法中进行操作.但是不过OC更偏向于Java这种方式,OC中如果一个对象需要被拷贝,他需要实现协议:<NSCopying>.<NSMutableCopying>从名字上我们可以看到,一个协议是用于不可变对象的,一个协议适用于可变对象的 首先来介绍一下对象的拷贝的概念吧:为什么要由对象的拷贝这么一个概念呢?看一个场

无需安装 vsftpd , 直接使用 FTP 来管理 docker 容器中的文件

无图无真相,先放个效果图: 背景 使用 docker 来跑一些服务很方便,但是有的时候想管理容器里面的文件却很麻烦 -- 一般常规做法有3种: 通过数据卷或数据卷容器的方式 启动容器的时候时候启动 vsftpd 或者 sshd 等服务,并开启端口映射,然后通过 ftp/sftp 连上去管理 进入容器的终端,通过命令行管理 但是这些做法都有一定的缺陷和不便: 1和2都是需要在启动容器的时候做一些配置,如果容器已经启动了就歇菜了.而且2需要额外的端口映射,占用主机的端口.3的做法比较 geek ,而

一起写框架-Ioc内核容器的实现-对象的调用-属性注入容器的对象(十)

实现功能 需求:在类的成员属性使用@Autowirde注解注入容器中的对象. 实现思路 要实现这个功能.我们首先要思考一个问题:类与类的关系是在调用的建立的,还是说在创建对象的时候就就将建立了? ---我实现的方案是,在在程序启动后,所有对象创建后直接就将对象的属性和属性之间的关系创建了.接下来我就用这个思路来实现,将根据@Autowirde建立对象与对象之间的关系. 为什么一定要对象全部创建后再实现对象与对象直接的关系呢? 这个是逻辑问题,如果对象没有创建完就建立对象与对象之间的关系,人家都还

一起写框架-Ioc内核容器的实现-对象的调用-方法注入容器的对象(十一)

实现功能 就是在方法的上面加入@Autowired注解,容器中的对象会注入到对应类型的参数. 注意:暂时实现注入一个对象.所有方法的参数列表的参数只能有一个. 实现思路 其实实现的思路和给字段注入的逻辑是一样的.遍历类所有的方法有没有@Autowired,有的就给它赋予容器中对应的对象. 实现步骤 1. 在AbstractApplicationContext类增加两个方法区分属性注入(autowiredField)和方法注入(autowiredMethod) 1 /** 2 * 属性注入 3 *

Spring中bean对象的生命周期

Spring提供了一些接口来提供一些方法,体现了bean对象在Spring容器中的生命周期 具体的过程可以体现为: 读取权限类名->构建一个类对象->用这个类对象通过无参构造器newInstance()构建对象 ↓ 调用set方法注入依赖 ↓ 如果这个Bean已经实现了BeanNameAware接口 调用它实现的setBeanName(String name)方法 此处传递的就是Spring配置文件中Bean的name值 ↓ 如果这个Bean已经实现了BeanFactoryAware接口 容器