// Person通过指针拥有string
class Person {
public:
Person(string name) { pName_ = new string(name); }
~Person() { delete pName_; } void printName() { cout << *pName_; } private:
string* pName_;
}; int main() { vector<Person> persons;
persons.push_back(Person("George")); persons.front().printName(); //这里会崩 cout << "Goodbye" << endl;
} //persons.push_back(Person("George")); 事实上该行代码可以分解成以下步骤
// 1. "George" 被构造
// 2. "George"的一个副本保存到(浅拷贝)
// 3. "George"被销毁 // Solution 1: 定义拷贝构造和拷贝赋值实现深拷贝
Person(const Person& rhs) {
pName_ = new string(*(rhs.pName()));
}
Person& operator=(const Person& rhs);
string* pName() const { return pName_; } // Solution 2: 禁用拷贝构造和拷贝赋值
// 对C++ 11,使用=delete
// for C++ 03, 声明但不定义
Person(const Person& rhs);
Person& operator=(const Person& rhs); // 如果禁用之后仍然需要拷贝,使用clone()
// 显式的拷贝
Person* clone() {
return (new Person(*(pName_)));
} // 更推荐方法2:
// 1. 因为拷贝构造和拷贝赋值经常并不需要
// 2. 使拷贝显式,隐式拷贝容易出现bug
// 3. clone可以利用多态实现虚构造函数,自动根据指针所指对象的类型拷贝基类或者派生类对象 class Dog {
public:
virtual Dog* clone() { return (new Dog(*this)); } //co-variant return type 允许覆写函数具有不同的返回类型,只要返回类型由基类的返回类型派生得到
}; class Yellowdog : public Dog {
virtual Yellowdog* clone() { return (new Yellowdog(*this)); }
}; void foo(Dog* d) { // d 是Yellowdog
//Dog* c = new Dog(*d); // c 是Dog,不是我们想要的
Dog* c = d->clone(); // c是Yellowdog
//...
//
} int main() {
Yellowdog d;
foo(&d);
} // C++ 11 的方法:
// shared_ptr<string> pName_;
// 大多数情况下用unique_ptr也可以, 但是跟STL container一起使用时必须使用shared_ptr,
// 因为STL容易要求元素时可拷贝的

C++进阶--拥有资源句柄的类(浅拷贝,深拷贝,虚构造函数)的更多相关文章

  1. C++_进阶之函数模板_类模板

     C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...

  2. 关于MFC资源句柄、ID和对象

    一.资源.句柄和ID 资源: MFC中的资源,如菜单.对话框.图标.工具条.对话框等,是windows创建的,并占用堆内存.windows在创建这些资源时候会给每个资源分配一个句柄,用来标记这些资源, ...

  3. 【python进阶】详解元类及其应用2

    前言 在上一篇文章[python进阶]详解元类及其应用1中,我们提到了关于元类的一些前置知识,介绍了类对象,动态创建类,使用type创建类,这一节我们将继续接着上文来讲~~~ 5.使⽤type创建带有 ...

  4. C++进阶--派生类的析构(虚析构函数,shared_ptr)

    //############################################################################ /* 在多态虚基类中声明一个虚析构函数 * ...

  5. Scala进阶之路-Scala特征类与unapply反向抽取

    Scala进阶之路-Scala特征类与unapply反向抽取 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Scala特征类分析 1>.Unit 答:用于定义返回值类型, ...

  6. C++ 类的深拷贝和浅拷贝完美解决

    //类的深拷贝和浅拷贝 #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; class Poin ...

  7. js进阶 10-7 简单的伪类选择器可以干什么

    js进阶 10-7 简单的伪类选择器可以干什么 一.总结 一句话总结:伪类选择器是冒号. 1.学而不用,有什么用? 多用啊,在项目中多用 2.简单的伪类选择器可以干什么? 除某元素以外,某元素的一切索 ...

  8. CPP_类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数

    类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数 // person.h #ifndef _PERSON_H_ #define _PERSON_H_ class Person{ public : ...

  9. C++类中函数(构造函数、析构函数、拷贝构造函数、赋值构造函数)

    [1]为什么空类可以创建对象呢? 示例代码如下: #include <iostream> using namespace std; class Empty { }; void main() ...

随机推荐

  1. mysql手动设置数据表的自增值

    设置表tablename的自增值从1开始自增值 alter table tablename auto_increment=1;

  2. 使用httputil中ReverseProxy反向代理遇到的坑

    坑描述,当POST ContentType=="application/x-www-form-urlencoded"时,反向代理报错:http: proxy error: http ...

  3. xdoj-1279(有趣的线段树--吉司机?!)

    题目链接 一 核心: f(x)=91 (x<=100) f(x)=x-10 (x>100) 那么同一区间就可能不同的操作,那么该怎么解决呢? 我门直到同一区间的数据属于同一类别的时候再进行 ...

  4. VMware安装CentOS以及CentOS的一些配置

    转:http://blog.csdn.net/u013082989/article/details/51911330

  5. C++ Tips

    1. 虚函数不能是内联的 因为“内联”是指“在编译期间用被调用的函数体本身来代替函数调用的指令,”但是虚函数的“虚”是指“直到运行时才能知道要调用的是哪一个函数.”如果编译器在某个函数的调用点不知道具 ...

  6. 《DSP using MATLAB》Problem5.33

    代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...

  7. VxWorks笔记

    利用vxWorks可裁减可动态链接特性进行模块调试的分析 a) 首先,可将root.c简化,去掉大部分不需要加载的模块和想要调试的模块,以加快系统启动速度. b) 如果vxworks加载的.o中引用了 ...

  8. HIDL学习笔记

    一.HIDL简单介绍 HIDL是Android8.0新出的一个技能,以service和client的方式实现hal接口,目的是想使Android系统和BSP解绑,使系统升级更加方便.HIDL的使用方法 ...

  9. mysqldump命令之常用选项

    ===============================================mysqldump常用选项-h, --host=name:服务器IP-u, --user=name:登录名 ...

  10. deno学习三 官方提供的方便deno 安装方式

    早起deno 使用了golang 开发,同时需要protobuf 进行数据的序列化以及反序列化处理 当前的deno 已经使用rust 进行了开发,同时官方提供的安装方式也很方便了,不需要 那么复杂的编 ...