函数的参数传递可以简单分类为“传值”和“传引用”。

声明函数时,形参带引用“&”,则函数调用时,是把实参所在的内存直接传给函数所开辟的栈内存。在函数内对形参的修改相当于对实参也进行修改。

声明函数时,形参不带引用,则函数调用时,是把实参拷贝一份作为形参。从内存上看,存在两个存放相同变量的区域,分别是实参和形参。在函数中对形参的修改,都不会对实参产生影响。函数退出后,形参所在的栈内存全部销毁。

对智能指针shared_ptr的通俗理解。

shared_ptr之所以能够做到在指针生命周期结束后自动销毁,得益于两个经典设计:

1)用类封装裸指针得到智能指针,在类的析构函数中,执行指针的delete操作;

2)类内有两个成员变量,一个是裸指针,一个是计数器;

当计数器计数归零时,智能指针自动调用其析构函数,销毁指针,释放内存。

智能指针作为函数的参数。

1)智能指针作为函数的传值参数,执行new操作

main函数片段如下,

  1. PointCloudPtr targetCloudPtr;
  2. targetCloudPtr = lidar_->GetNewCloud();
  3. if (targetCloudPtr == )
  4. return;
  5.  
  6. PointCloudPtr processTarPtr(new PointCloudType);
  7.  
  8. ExtrPlanes_->run_Plane_Extraction(targetCloudPtr, processTarPtr);
  9. std::cout << "process target point cloud size : " << processTarPtr->points.size() << std::endl;

声明了一个PCL的智能指针 processTarPtr ,执行new操作之后, processTarPtr 中便有了一个 PointCloudType 的裸指针成员变量,同时计数器+1,此时计数器=1.

函数 run_Plane_Extraction 的定义如下,

  1. void Extr_PLANEFEATURE::run_Plane_Extraction(PointCloudPtr inPtr, PointCloudPtr outPtr)
  2. {
  3. PointCloudPtr MLS_pointcloud(new PointCloudType);
  4. //
  5. // 给MLS_pointcloud赋值
  6. //
  7.  
  8. outPtr = MLS_pointcloud;
  9. }

实参processTarPtr将拷贝一份作为形参,同时计数器+1,此时计数器=2.

在函数中对形参的修改都不会对实参产生影响。因此,函数执行完毕,outPtr所指向的栈内存全部销毁。

此时,在main函数中读取processTarPtr指针的值,返回值为0。此时程序并不会崩溃。等到这个0值对main函数中其他操作产生影响时,程序才会报错。

  1. Invalid or empty point cloud dataset given!
  2. Invalid or empty point cloud dataset given!
  3. [ndtMap-] process has died [pid , exit code -, cmd /home/gordon/fase_ws/devel/lib/ddd_wall_mapping/ndtMap __name:=ndtMap __log:=/home/gordon/.ros/log/d150b30c-aecf-11e9--9cda3e942fe1/ndtMap-.log].
  4. log file: /home/gordon/.ros/log/d150b30c-aecf-11e9--9cda3e942fe1/ndtMap-*.log

2)智能指针作为函数的传值参数,不执行new操作

main函数做如下修改,即不执行智能指针的new操作。

  1. PointCloudPtr targetCloudPtr;
  2. targetCloudPtr = lidar_->GetNewCloud();
  3. if (targetCloudPtr == )
  4. return;
  5.  
  6. PointCloudPtr processTarPtr;
  7.  
  8. ExtrPlanes_->run_Plane_Extraction(targetCloudPtr, processTarPtr);
  9. std::cout << "process target point cloud size : " << processTarPtr->points.size() << std::endl;

声明了一个智能指针而不进行new操作,那么这个指针一直个是空指针,即null。计数器一直为0.

函数run_Plane_Extraction的调用结果与上面例子相同。回到main函数,访问空指针processTarPtr,程序立即崩溃。报错如下,

  1. ndtMap: /usr/include/boost/smart_ptr/shared_ptr.hpp:: typename boost::detail::sp_member_access<T>::type boost::shared_ptr<T>::operator->() const [with T = pcl::PointCloud<pcl::PointXYZI>; typename boost::detail::sp_member_access<T>::type = pcl::PointCloud<pcl::PointXYZI>*]: Assertion `px != ' failed.
  2. [ndtMap-] process has died [pid , exit code -, cmd /home/gordon/fase_ws/devel/lib/ddd_wall_mapping/ndtMap __name:=ndtMap __log:=/home/gordon/.ros/log/d150b30c-aecf-11e9--9cda3e942fe1/ndtMap-.log].
  3. log file: /home/gordon/.ros/log/d150b30c-aecf-11e9--9cda3e942fe1/ndtMap-*.log

3)智能指针作为函数的传引用参数

为解决上述问题,函数 run_Plane_Extraction 对形参的修改能够等同于对形参进行修改。即,我们希望能够在函数 run_Plane_Extraction 结束后,将其中的形参outPtr所指向的内存保存下来。

对于上述2个例子,其修改方式都一样,把函数 run_Plane_Extraction 的形参改成传引用参数

  1. void Extr_PLANEFEATURE::run_Plane_Extraction(PointCloudPtr inPtr, PointCloudPtr& outPtr)
  2. {
  3. PointCloudPtr MLS_pointcloud(new PointCloudType);
  4. //
  5. // 给MLS_pointcloud赋值
  6. //
  7.  
  8. outPtr = MLS_pointcloud;
  9. }

传引用参数,把实参所在的内存直接传递给函数作为形参,对形参的修改等同于对实参的修改。

函数 run_Plane_Extraction 结束以后,不会销毁实参指向的内存!

问题成功解决!

PCL智能指针疑云 <三> 智能指针作为函数的传值参数和传引用参数的更多相关文章

  1. c指针点滴三(指针运算)

    #include <stdio.h> #include <stdlib.h> void main3() { ; int *p = &num; p++;//不可预测的值 ...

  2. C和指针 第三章 指针常量与常量指针

    c语言中声明常量的两种方式 const int value int const value 如果要声明常量的指针,即指向常量的指针,则可以参考上面的常量声明修改一下 const int *ptr in ...

  3. C语言指针(三)指针传递给函数

    实例1:传递一个无符号的long型指针给该函数 #include<stdio.h>#include<time.h>void getSeconds(unsignedlong*pa ...

  4. 指针数组与带参main函数

    (一)指针数组 指针数组就是每一个元素存放一个地址,相当于一个指针变量.如:int *p[4]指针数组比较适合用来指向若干字符串,使得处理字符串更加灵活.例如,现在要将若干字符串按字母顺序由小到大输出 ...

  5. C++ 11 智能指针(shared_ptr)类成员函数详解

    C++ 11 模板库的 <memory> 头文件中定义的智能指针,即 shared_ptr 模板类,用来管理指针的存储,提供有限的内存回收函数,可同时与其他对象共享该管理功能. share ...

  6. const 指针的三种使用方式

    ///////////////////////const 指针的三种状态///////////////////// 注意:const 的前后顺序 const 在类型之前 ---可以修改指针包含的地址, ...

  7. [C和指针]第三部分

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  8. iOS 认识runtime 中的三个指针 isa , IMP , SEL

    runtime中函数调用经常被提及的三个概念 isa,IMP,SEL 一  isa:是类指针,之所以说isa是指针是因为Class其实是一个指向objc_class结构体的指针,而isa 是它唯一的私 ...

  9. C语言提高 (3) 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间

    1 作业讲解 指针间接操作的三个必要条件 两个变量 其中一个是指针 建立关联:用一个指针指向另一个地址 * 简述sizeof和strlen的区别 strlen求字符串长度,字符数组到’\0’就结束 s ...

随机推荐

  1. 在CentOS 8 Linux中安装使用Cockpit服务器管理软件

    在本文中,我们将帮助您在CentOS 8服务器中安装Cockpit Web 控制台,以管理和监视本地系统以及网络环境中的Linux服务器.您还将学习如何将远程Linux主机添加到Cockpit并在Ce ...

  2. HDU 2973 YAPTCHA (威尔逊定理)

    YAPTCHA Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  3. 思考--mysql 分库分表的思考

    查询不在分库键上怎么办,扫描所有库?由于分库了,每个库扫描很快?所以比单个表的扫描肯定快,可以这样理解吗. 多表jion怎么弄,把内层表发给每个分库吗? citus,tidb 都有这些问题,citus ...

  4. HDU-4507-吉哥系列故事-恨7不成妻

    题目描述 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: 2+1+4=7 7+7=7*2 ...

  5. ubuntu 安装 CUDA、 cuDNN 的tips

    CUDA 查看驱动兼容性:https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html 查看GCC 与CUDA 驱动版本的兼容性 ...

  6. Centos7安装Beanstalkd

    安装 //安装 yum -y install beanstalkd --enablerepo=epel //查看版本 beanstalkd -v //启动 -b断电重启会恢复 /usr/bin/bea ...

  7. Quatrz + Spring

    实例工程结构: 配置: pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=" ...

  8. windows 2008 创建域服务器问题 账户密码不符合要求

    windows 2008新建域时,本地administrator账户将成域Administrator账户.无法新建域,因为本地administrator账户密码不符合要求.*解决办法:很多人都会想到在 ...

  9. mysql小数和类型转换函数

    保留两位小数 SELECT ROUND( 123456789.3563898,2),TRUNCATE(123456789.3563898,2),FORMAT(123456789.3563898,2); ...

  10. jfinal layui easyexcel 实现文件的上传下载

    jfinal  layui easyexcel  这三样开源技术这里就不多介绍了,自行百度了解吧,他们的组合算是一个很高效又不失美观的操作体验. 操作主要分以下几步: 1.建立jfinal的操作环境, ...