[转] C++中为什么要用指针,而不直接使用对象?
原文点击这里
问题描述
我刚从 Java 转到使用 C++ 进行面向对象开发,我发现一个很让我非常困惑的问题:C++ 中经常出现使用对象指针,而不是直接使用对象本身的代码,比如下面这个例子:
C++
Object myObject = new Object;
1
Object myObject = new Object;
而不是使用:
C++
Object myObject;
1
Object myObject;
要不就是调用对象的方法(比如 testFunc())时不使用这种方式:
C++
myObject.testFunc();
1
myObject.testFunc();
而是得写成这样:
C++
myObject->testFunc();
1
myObject->testFunc();
我不明白代码为什么要写成这种形式,我能想到的是指针方式是直接访问内存,这么写代码可以提高代码效率以及执行速度,是这样的么?
最佳回复
来自 Joseph Mansfield
非常不幸,你在代码中遇到这么多的动态内存分配,但这个只能说明有现在有太多不合格的 C++ 程序员。
这么说吧,你的两个问题本质上是同个问题。第一个问题是,应该何时使用动态分配(使用 new 方法)?第二问题是,什么时候该使用指针?
最先要牢记的重点是,你应该根据实际需求选择合适的方法。 一般来说,使用定义对象的方式比起使用手工动态分配(或new指针)的方式会更加合理以及安全。
动态分配
你的提问中,所列出的两种分配对象方式的主要区别在于对象的生存期。通过 Object myObject 方式定义对象,对象的生存期是在其作用域内自维护(automatic storage),这个意味着程序离开对象的作用域之后,对象将被自动销毁。当通过 new Object() 方式分配对象时,对象的生存期是动态的,这个意味着若不显式地 detete 对象,对象将一直存在。你应该只在必要的时候使用动态分配对象。换句话说,只要有可能,你应该首选定义可自维护的对象。
这里是两个常见需要动态分配对象的情况:
分配不限制作用域的对象,对象存储在其特定的内存中,而不是在内存中存储对象的拷贝。如果对象是可以拷贝/移动的,一般情况下你应该选择使用定义对象的方式。
定义的对象会消耗大量内存,这时可能会耗尽栈空间。如果我们永远不需要考虑这个问题那该多好(实际大部分情况下,我们真不需要考虑),因为这个本身已经超出 C++ 语言的范畴,但不幸的是,在我们实际的开发过程中却不得不去处理这个问题。
当你确实需要动态分配对象时,应该将对象封装在一个智能指针(smart pointer)或其他提供RAII机制的类型中(类似标准的 container)。智能指针提供动态对象的所有权语义(ownership),具体可以看一下std::unique_ptr 和 std::shared_ptr 这两个例子。如果你使用得当,基本上可以避免自己管理内存(具参见 Rule of Zero)。
指针
当然,不使用动态分配而采取原始指针(raw pointer)的用法也很常见,但是大多数情况下动态分配可以取代指针,因此一般情况应该首选动态分配的方法,除非你遇到不得不用指针的情况。
使用引用语义(reference semantics)的情况。有时你可能需要通过传递对象的指针(不管对象是如何分配的)以便你可以在函数中去访问/修改这个对象的数据(而不是它的一份拷贝),但是在大多数情况下,你应该优先考虑使用引用方式,而不是指针,因为引用就是被设计出来实现这个需求的。注意,采用这种方式,对象生存期依旧在其作用域内自维护。当然,如果通过传递对象拷贝可以满足要求的情况下是不需要使用引用语义。
使用多态的情况。通过传递对象的指针或引用调用多态函数(根据入参类型不同,会调用不同处理函数)。如果你的设计就是可以传递指针或传递引用,显然,应该优先考虑使用传递引用的方式。
对于入参对象可选的情况,常见的通过传递空指针表示忽略入参。如果只有一个参数的情况,应该优先考虑使用缺省参数或是对函数进行重载。要不然,你应该优先考虑使用一种可封装此行为的类型,比如 boost::optional (或者std::optional,已经在 C++ 14 草案 n3797 14 中发布 )。
通过解耦编译类型依赖减少编译时间的情况。使用指针的一个好处在于可以用于前向声名(forward declaration)指向特定类型(如果使用对象类型,则需要定义对象),这种方式可以减少参与编译的文件,从而显著地提高编译效率,具体可以看 Pimpl idiom 用法。
与C库或C风格的库交互的情况。此时只能够使用指针,这种情况下,你要确保的是指针使用只限定在必要的代码段中。指针可以通过智能指针的转换得到,比如使用智能指针的get成员函数。如果C库操作分配的内存需要你在代码中维护并显式地释放时,可以将指针封装在智能指针中,通过实现 deleter 从而可以有效的地释放对象。
[转] C++中为什么要用指针,而不直接使用对象?的更多相关文章
- c++中的引用与指针的区别
http://blog.csdn.net/lyd_253261362/article/details/4323691 c++中的引用与指针的区别 ★ 相同点: 1. 都是地址的概念: 指针指向一块内存 ...
- MFC关于多线程中传递窗口类指针时ASSERT_VALID出错的另类解决 转
MFC关于多线程中传递窗口类指针时ASSERT_VALID出错的另类解决 在多线程设计中,许多人为了省事,会将对话框类或其它类的指针传给工作线程,而在工作线程中调用该类的成员函数或成员变量等等. ...
- VC++中有关句柄和指针及其转换(转)
原文转自 https://blog.csdn.net/jearmy/article/details/47030011 1.MFC窗口的句柄和指针的转换 (1) 一般窗口对象都会有一个其对应的句柄变量, ...
- C++中引用传递与指针传递区别
C++中引用传递与指针传递区别 在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的: 指针传递参数本质上是值传递的方式,它所传递的是一个地址值.值传递过程 ...
- LWIP协议中tcp_seg结构相关指针的个人理解
我曾经写在新浪博客上面,后来复制到这,图片就不行了. 原文地址转载 LWIP协议中tcp_seg结构相关指针的个人理解(http://blog.sina.com.cn/s/blog_7e586985 ...
- C语言中的数组和指针以及字符串
数组名同时也是该数组首元素的地址,而指针提供了一种用来使用地址的符号方法,因此指针能够很有效地处理数组. 将一个整数加给指针,这个整数会和指针所指类型的字节数相乘,然后所得的结果会加到初始地址上 da ...
- MFC类中获得其它类指针
当用VC++的Application Wizard生成除了CDialog Basiced以外的应用程序时,将自动产生视图类.文档类.主帧窗口类.应用程序类等等.一般来说,程序的核心数据及操作在文档类中 ...
- C++中使用const修饰指针
在本文中呢,主要讲解四个方面,即:常量数据的与否和常量指针的与否中const如何对指针进行修饰: 1.指向非常量数据的常量指针 对于一个指向非常量数据的常量指针,我们应该清楚的知道,在这我们注重的是指 ...
- C++中值传递、指针传递、引用传递的总结
C++中值传递.指针传递.引用传递的总结 指针传递和引用传递一般适用于:函数内部修改参数并且希望改动影响调用者.对比值传递,指针/引用传递可以将改变由形参"传给"实参(实际上就 ...
- 尝试在条件“$(_DeviceSdkVersion) >= 21”中对计算结果为“”而不是数字的“$(_DeviceSdkVersion)
晚上搞xamarin ,运行xamarin项目好好的,不知道怎么回事,一次运行xamarin android项目的时候,部署失败,以前也是遇到这样的错误. 尝试在条件"$(_DeviceSd ...
随机推荐
- 网站图片的轮播JS代码
这是几个网站的轮播JS效果,实现图片按照时间来切换,目前有几个站实现该功能,特别是浴室柜网站改版前,以下就是JS具体内容可以自己改下路径就可以用的linkarr = new Array();picar ...
- 一段自适应的CSS代码
一段自适应HTML5的CSS代码,该代码在陕西特产使用过,手机端效果还好,就是PC端看起来没那么大气,比较窄屏 * { transition-property: all; -ms-transition ...
- php的trie_filter扩展安装敏感词查找
#编译libiconv ./configure make make install #编译libdatrie-0.2.11 ./configure LDFLAGS=-L/usr/local/lib L ...
- js 解析url
以前解析uri都是去找网上的代码,用起来不怎么顺手,刚好自己前段时间做项目的时候需要用到,于是就自己写了一个,欢迎个位提出宝贵意见. getUrlParam (name) { //解析url var ...
- I/O系统(二)
程序查询流程1测试指令,查询IO设备是否就绪.2传送指令,当已经就绪时,执行传送功能.3转移指令,未就绪时,转移至继续测试IO设备的状态.当需要启动某一IO设备时,必须将该程序插入到现行程序中.1,由 ...
- Day1数据结构和算法
2019-02-27 程序设计=数据结构+算法 数据结构就是关系,是数据元素相互之间存在的关系集合 逻辑结构:数据对象中数据元素的相互关系 集合结构:集合里的数据元素除了同属于一个集合外没有其他关系 ...
- 微信小程序登录流程
小程序登录流程 参考 app.js需要做的 1,首先通过wx.login()拿到code,成功之后,发送数据,请求接口,把code发送给后端,换区openid,sessionKey,unionId,把 ...
- 3,postman的变量写法和collection
1,环境变量和全局变量的添加和引用 pm.globals.get("variable_key");可以引用环境变量 2,collection的使用 当在tests中使用文件变量的时 ...
- 20165213 Exp5 MSF基础应用
Exp5 MSF基础应用 实践内容 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 1.1一个主动攻击实践,如ms08_067; (1分) 1.2 一 ...
- Vmware Workstation - linux系统下 VmTools 安装
程序版本 : VMware® Workstation 14 Pro 系统环境 : win10 64位下 ubuntu-14.04.5-desktop-amd64 问题:在运行linux系统过程中,de ...