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

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

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

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

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

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

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

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

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

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

main函数片段如下,

PointCloudPtr targetCloudPtr;
targetCloudPtr = lidar_->GetNewCloud();
if (targetCloudPtr == )
return; PointCloudPtr processTarPtr(new PointCloudType); ExtrPlanes_->run_Plane_Extraction(targetCloudPtr, processTarPtr);
std::cout << "process target point cloud size : " << processTarPtr->points.size() << std::endl;

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

函数 run_Plane_Extraction 的定义如下,

void Extr_PLANEFEATURE::run_Plane_Extraction(PointCloudPtr inPtr, PointCloudPtr outPtr)
{
PointCloudPtr MLS_pointcloud(new PointCloudType);
//
// 给MLS_pointcloud赋值
// outPtr = MLS_pointcloud;
}

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

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

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

Invalid or empty point cloud dataset given!
Invalid or empty point cloud dataset given!
[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].
log file: /home/gordon/.ros/log/d150b30c-aecf-11e9--9cda3e942fe1/ndtMap-*.log

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

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

PointCloudPtr targetCloudPtr;
targetCloudPtr = lidar_->GetNewCloud();
if (targetCloudPtr == )
return; PointCloudPtr processTarPtr; ExtrPlanes_->run_Plane_Extraction(targetCloudPtr, processTarPtr);
std::cout << "process target point cloud size : " << processTarPtr->points.size() << std::endl;

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

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

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.
[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].
log file: /home/gordon/.ros/log/d150b30c-aecf-11e9--9cda3e942fe1/ndtMap-*.log

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

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

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

void Extr_PLANEFEATURE::run_Plane_Extraction(PointCloudPtr inPtr, PointCloudPtr& outPtr)
{
PointCloudPtr MLS_pointcloud(new PointCloudType);
//
// 给MLS_pointcloud赋值
// outPtr = MLS_pointcloud;
}

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

函数 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. redhat java配置

    原来的java版本为1.4 whereis java后 将java原来的目录全部删除 拿来新的1.8的安装好的java包 vi /etc/profile插入 JAVA_HOME=/usr/local/ ...

  2. 13.56Mhz/NFC读写器天线阻抗匹配调试步骤-20191128

    相关原文: https://blog.csdn.net/wwt18811707971/article/details/80641432 http://www.52rd.com/Blog/Detail_ ...

  3. [转帖]java必备的开发知识和技能

    java必备的开发知识和技能 https://blog.csdn.net/qq_34405062/article/details/89389646 学习一下java 其实上学那会儿学的 早就过时加落伍 ...

  4. html中的锚点设置

    html中的锚点 一.页面内跳转的锚点设置 页面内的跳转需要两步: 方法一: ①:设置一个锚点链接去找喵星人:(注意:href属性的属性值最前面要加#) ②:在页面中需要的位置设置锚点<a na ...

  5. Kibana server is not ready yet出现的原因

    第一点:KB.ES版本不一致(网上大部分都是这么说的) 解决方法:把KB和ES版本调整为统一版本 第二点:kibana.yml中配置有问题(通过查看日志,发现了Error: No Living con ...

  6. Flask运行时指定端口

    在项目入口文件server.php中,有如下代码 if __name__ == '__main__': app.run(debug=True,port=8000) 但是在进入虚拟机中运行 flask ...

  7. flume复习(一)

    关于flume官方文档介绍可以去:http://flume.apache.org/看看.接下来就介绍一下关于我个人对flume的理解 一.flume介绍: 1.flume是一个分布式.可靠.和高可用的 ...

  8. CentOS下配置Apache HTTPS

    一.安装Apache支持SSL/TLS yum install mod_ssl openssl 二.创建证书 证书(Cerificate)的基本作用是将一个公钥和安全个体(个人.公司.组织等)的名字绑 ...

  9. Centos7安装Python3的方法[转]

    Centos7安装Python3的方法   由于centos7原本就安装了Python2,而且这个Python2不能被删除,因为有很多系统命令,比如yum都要用到. [root@VM_105_217_ ...

  10. mybatis捕获sql工具

    今天给大家分享一款好用的软件 https://ssrss.space/register?aff=982689 日志级别必须是debug