一

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

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

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

二

对智能指针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. pom文件中引入依赖成功了,但是jar包找不着

    编写代码的时候总是会碰到各种奇奇怪怪的问题,最近引入依赖的时候发现依赖虽然引入成功了,而且查看仓库,仓库中也存在该jar包,但是项目代码中并没有找到该jar包,重新导入reimport各种都试了还是不 ...

  2. 开发完成的springboot项目扩展 swagger

    第一步:pom.xml 引入 swagger 配置 <swagger.version>2.9.2</swagger.version> <!--swagger start- ...

  3. React基础篇学习

    到今天为止, 使用react已经一年了, 现在整理一下入门时的一些重要知识, 帮助想要学习react的同学们理解某些内容. React 元素 React 元素,它是 React 中最小基本单位,我们可 ...

  4. Vue.js官方文档学习笔记(三)创建Vue实例

    创建Vue实例 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的: var vm=new Vue({ //选项 }) Vue的设计受到了mvvm的启发 当创建一个 Vue 实 ...

  5. <<C++ Primer>> 第四章 表达式

    术语表 第 4 章 表达式 算术转换(arithmetic conversion): 从一种算术类型转换成另一种算术类型.在二元运算符的上下文中,为了保留精度,算术转换通常把较小的类型转换成较大的类型 ...

  6. sql server 角度与弧度相互转换的函数radians(x)和degrees(x)

    --RANDIANS(x)将参数x由角度转换为弧度 --DEGREES(x)将参数x由弧度转换为角度. 示例:select RADIANS(90.0), RADIANS(180.0), DEGREES ...

  7. __main__ 变量

    1. 摘要 通俗的理解__name__ == '__main__':假如你叫小明.py,在朋友眼中,你是小明(__name__ == '小明'):在你自己眼中,你是你自己(__name__ == '_ ...

  8. 【抓包工具】使用Fiddler关于“由于目标计算机积极拒绝,无法连接。”的解决方案

    今天使用Fiddler的时候遇到下面这个问题:在地址栏想打开个一般处理程序,出现连接本机失败的提示,如下图: 而这在我没打开Fiddler的时候是显示正常的. 查看Fiddler,在嗅探 -> ...

  9. webpack3 打包

    1. 基于 webpack 3.0 2.步骤.说明 2.1 webpack 本地初始化.安装基本包 npm init         >  package.json npm i  webpack ...

  10. Django 解决跨域问题(写入到中间件中)

    class MiddlewareMixin(object): def __init__(self, get_response=None): self.get_response = get_respon ...