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

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

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

对智能指针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. 执行python程序 出现三部曲

    1.执行一个python程序 ,会产生一个进程 ,然后会在内存生成一份内存空间 先把python解释器代码加载到内存里, python解释器代码就是C语言代码 2. 然后再把 自己写的python文件 ...

  2. python 并发编程 多线程 互斥锁

    互斥锁 并行变成串行,牺牲效率 保证数据安全,实现局部串行 保护不同的数据,应该加不同的锁 现在一个进程 可以有多个线程 所有线程都共享进程的地址空间 实现数据共享 共享带来问题就会出现竞争 竞争就会 ...

  3. python 爬取网页内的代理服务器列表(需调整优化)

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date : 2017-08-30 20:38:23 # @Author : EnderZhou (z ...

  4. openvswitch笔记

    下载解压sudo wget http://openvswitch.org/releases/openvswitch-2.4.1.tar.gztar -xvf openvswitch-2.4.1.tar ...

  5. 【3.1】【mysql基本实验】mysql复制(主从复制/异步复制/半同步复制,一主一从)

    关键词:mysql复制(异步复制),mysql异步复制 核心原理: mysql 复制流程原理 一个事务在 mysql异步复制中的流程与生命周期 一个事务,在传统半同步的复制流程 #mysql主从基本实 ...

  6. window7下安装Elasticseach5.2.2

    1. 安装JDK,至少1.8.0_73以上版本 java -version 2. 下载和解压缩Elasticsearch安装包,目录结构 3. 启动Elasticsearch:bin\elastics ...

  7. AppCan打包问题

    在AppCan IDEA打包的时候出了错误, Failed reading value of registry key: Software\JavaSoft\Java Runtime Environm ...

  8. 集成学习-组合策略与Stacking

    集成学习是如何把多个分类器组合在一起的,不同的集成学习有不同的组合策略,本文做个总结. 平均法 对数值型输出,平均法是最常用的策略,解决回归问题. 简单平均法 [h(x)表示基学习器的输出] 加权平均 ...

  9. 使用Jenkins结合Gogs和SonarQube对项目代码进行测试、部署、回滚,以及使用keepalived+haproxy调度至后端tomcat

    0 环境说明 主tomcat:192.168.0.112 备tomcat:192.168.0.183 haproxy+keepalived-1:192.168.0.156 haproxy+keepal ...

  10. type=file 上传图片限制 类型和尺寸 方法

    <form> <input type="file" name="pic" id="pic" accept="im ...