C++ 中经常出现使用对象指针,而不是直接使用对象本身的代码,比如下面这个例子:

 Object *myObject = new Object;

  而不是使用:

 myObject.testFunc();

  要不就是调用对象的方法(比如 testFunc())时不使用这种方式:

 myObject->testFunc();
 

  我不明白代码为什么要写成这种形式,我能想到的是指针方式是直接访问内存,这么写代码可以提高代码效率以及执行速度,是这样的么?

最佳回复来自 Joseph Mansfield

  非常不幸,你在代码中遇到这么多的动态内存分配,但这个只能说明有现在有太多不合格的 C++ 程序员。

  这么说吧,你的两个问题本质上是同个问题。第一个问题是,应该何时使用动态分配(使用 new 方法)?第二问题是,什么时候该使用指针?

  最先要牢记的重点是,你应该根据实际需求选择合适的方法。 一般来说,使用定义对象的方式比起使用手工动态分配(或new指针)的方式会更加合理以及安全。

动态分配

  你的提问中,所列出的两种分配对象方式的主要区别在于对象的生存期。通过 Object myObject 方式定义对象,对象的生存期是在其作用域内自维护(automatic storage),这个意味着程序离开对象的作用域之后,对象将被自动销毁。当通过 new Object() 方式分配对象时,对象的生存期是动态的,这个意味着若不显式地 detete 对象,对象将一直存在。你应该只在必要的时候使用动态分配对象。换句话说,只要有可能,你应该首选定义可自维护的对象。

  这里是两个常见需要动态分配对象的情况:

  1. 分配不限制作用域的对象,对象存储在其特定的内存中,而不是在内存中存储对象的拷贝。如果对象是可以拷贝/移动的,一般情况下你应该选择使用定义对象的方式。
  2. 定义的对象会消耗大量内存,这时可能会耗尽栈空间。如果我们永远不需要考虑这个问题那该多好(实际大部分情况下,我们真不需要考虑),因为这个本身已经超出 C++ 语言的范畴,但不幸的是,在我们实际的开发过程中却不得不去处理这个问题。

  当你确实需要动态分配对象时,应该将对象封装在一个智能指针(smart pointer)或其他提供RAII机制的类型中(类似标准的 container)。智能指针提供动态对象的所有权语义(ownership),具体可以看一下std::unique_ptr 和 std::shared_ptr 这两个例子。如果你使用得当,基本上可以避免自己管理内存(具参见 Rule of Zero)。

指针

  当然,不使用动态分配而采取原始指针(raw pointer)的用法也很常见,但是大多数情况下动态分配可以取代指针,因此一般情况应该首选动态分配的方法,除非你遇到不得不用指针的情况。

  1. 使用引用语义(reference semantics)的情况。有时你可能需要通过传递对象的指针(不管对象是如何分配的)以便你可以在函数中去访问/修改这个对象的数据(而不是它的一份拷贝),但是在大多数情况下,你应该优先考虑使用引用方式,而不是指针,因为引用就是被设计出来实现这个需求的。注意,采用这种方式,对象生存期依旧在其作用域内自维护。当然,如果通过传递对象拷贝可以满足要求的情况下是不需要使用引用语义。

  2. 使用多态的情况。通过传递对象的指针或引用调用多态函数(根据入参类型不同,会调用不同处理函数)。如果你的设计就是可以传递指针或传递引用,显然,应该优先考虑使用传递引用的方式。

  3. 对于入参对象可选的情况,常见的通过传递空指针表示忽略入参。如果只有一个参数的情况,应该优先考虑使用缺省参数或是对函数进行重载。要不然,你应该优先考虑使用一种可封装此行为的类型,比如 boost::optional (或者std::optional,已经在 C++ 14 草案 n3797 14 中发布 )。

  4. 通过解耦编译类型依赖减少编译时间的情况。使用指针的一个好处在于可以用于前向声名(forward declaration)指向特定类型(如果使用对象类型,则需要定义对象),这种方式可以减少参与编译的文件,从而显著地提高编译效率,具体可以看 Pimpl idiom 用法。

  5. 与C库或C风格的库交互的情况。此时只能够使用指针,这种情况下,你要确保的是指针使用只限定在必要的代码段中。指针可以通过智能指针的转换得到,比如使用智能指针的get成员函数。如果C库操作分配的内存需要你在代码中维护并显式地释放时,可以将指针封装在智能指针中,通过实现 deleter 从而可以有效的地释放对象。

C++-对象指针的滥用的更多相关文章

  1. delete 类对象指针的注意事项]

    http://blog.csdn.net/infoworld/article/details/45560219 场景:1. C++类有构造和析构函数,析构函数是在类对象被delete时(或局部变量自动 ...

  2. C++:向函数传递对象(对象、对象指针、对象引用)

    3.5.1   使用对象作为函数参数,其方法与传递基本类型的变量相同 //例3.21 使用对象作为函数参数 #include<iostream> using namespace std; ...

  3. C++:对象指针

    对象指针概念:每一个对象在初始化后都会在内存中占有一定的空间.因此,既可以通过对象名访问, 也可以通过一个对象地址来访问一个对象.对象指针就是用于存放对象地址的变量. 声明对象指针的一般语法格式为:类 ...

  4. 对象指针与this指针

    对象指针分为三大类 [1]指向对象的指针 [2]指向对象成员的指针(数据类) [3]指向对象成员的指针(函数类) #include<iostream> using namespace st ...

  5. MFC通过对话框窗口句柄获得对话框对象指针

       C***Dialog* pWnd= (C***Dialog*)FromHandle(hWnd); //由句柄得到对话框的对象指针    pWnd->xxx( );              ...

  6. c++ 对象指针参数和对象引用参数02

    对象指针作为函数参数和对象引用作为函数参数都比对象作为函数参数要用的更为普遍 传对象指针和传对象引用作为实参,那么实参在函数里发生了变话,那么相应的对象本身也会发生变化,二传递对象本身作为实参的话,实 ...

  7. c++对象指针-01(转载)

    1.指向对像的指针在建立对像时,编译系统会为每一个对像分配一定的存储空间,以存放其成员,对像空间的起始地址就是对像的指针.可以定义一个指针变量,用来存和对像的指针.如果有一个类:class Time{ ...

  8. 值为NULL的对象指针

    相信大家对NULL不会很陌生,NULL 是一个标准规定的宏定义,用来表示空指针常量,当一个指针变量被赋值为NULL时,表示它不再指向任何有效地址,无法在访问任何数据.在VS2012库文件stdio.h ...

  9. C++二维数组、指针、对象数组、对象指针

    项目中用到,随手记一下: 1.二维数组.与指针 创建二维数组指针的方式: a.已知一维的大小 1 int **array=new int *[rows]; 2 (for int i=0;i<ro ...

随机推荐

  1. maven的核心概念——POM

    Project Object Model:项目对象模型.将Java工程的相关信息封装为对象作为便于操作和管理的模型.Maven工程的核心配置.可以说学习Maven就是学习pom.xml文件中的配置. ...

  2. javascript 基础整理

    js编码标准 参考 数据类型 注意事项

  3. 吴裕雄--天生自然HADOOP操作实验学习笔记:hdfs分布式文件系统安装

    实验目的 复习安装jdk 学习免密码登录 掌握安装配置hdfs集群的方法 掌握hdfs集群的简单使用和检查其工作状态 实验原理 1.hdfs是什么 hadoop安装的第一部分是安装hdfs,hdfs是 ...

  4. 关于牛客网C语言结构体位域(bit-fields)的一道题

    题目链接地址: https://www.nowcoder.com/questionTerminal/f4e20747a2dd4649bac0c028daa234f4 来源:牛客网 低地址字节 Byte ...

  5. JS表单验证源码(带错误提示及密码等级)

    先晒图 index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  6. [POI2004]PRZ [枚举子集]

    怎么全是 模拟退火 啊,这明明是个 枚举子集 的板子题. 考虑 \(n \leq 16\) 二进制没错了.. \(dt_i\) 表示 \(i\) 这个状态下 \(\max{t_j}\),\([\tex ...

  7. springMVC请求访问的整个过程

    //以上个随笔(springMVC项目配置文件)为基础,详述springMVC请求的整个过程流向 web.xml                                            ...

  8. 订阅消息---由于微信小程序取消模板消息,限只能开发订阅消息

    订阅消息开发步骤: 1.小程序管理后台添加订阅消息的模板 2.小程序前端编写调用(拉起)订阅授权 wx.requestSubscribeMessage({ tmplIds: ['34fwe1211xx ...

  9. R语言读写数据

    R语言读写数据 一般做模型的时候,从外部的excel中读入数据,我现在常用的比较多的是read_csv(file) 读入之前先把excel数据转化成.csv格式 同样的把结果输出来的时候用的是writ ...

  10. 4 Values whose Sum is 0 UVA 1152

    题目链接:https://vjudge.net/problem/UVA-1152 这题题意就是在四个集合内.每个集合分别里挑一个数a,b,c,d,求a+b+c+d=0有多少种选法. 暴力的话就是四重循 ...