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

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

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

对智能指针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. PostgreSQL INSERT ON CONFLICT不存在则插入,存在则更新

    近期有一个需求,向一张数据库表插入数据,如果是新数据则执行插入动作,如果插入的字段和已有字段重复,则更新该行对应的部分字段 1. 创建测试表 create table meta_data ( id s ...

  2. stack的常见用法

    stack的常见用法 栈是什么? 栈是一种先进后出的容器 栈的定义 引入头文件 # include <stack> using namespace std; 定义栈 可以定义任何类型的栈 ...

  3. 01Spring基于xml的IOC配置--入门

    01Spring基于xml的IOC配置 1.创建一个普通的maven工程 1.1 选择maven,不用骨架,点击下一步. 1.2 填写GroupId.ArtifactId.Version.填完点击下一 ...

  4. 剑指offer-5:十进制转二进制

    一.二进制中‘1’的个数 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. public class Solution { public int NumberOf1(int n) { ...

  5. 利用sql报错帮助进行sql注入

    我们可以利用sql报错帮助进行sql注入,这里以sql server 为例: sql查询时,若用group by子句时,该子句中的字段必须跟select 条件中的字段(非聚合函数)完全匹配,如果是se ...

  6. 生产服务器上安装Python

    2018-05-17 生产环境的服务器(以下简称内网服务器)由于安全限制,可能无法连接外网.这种情况下将无法直接使用pip命令安装python的包 一.更改pip源 - 默认pip是使用Python官 ...

  7. Pycharm新建第一个Django项目

    1:安装django 打开Pycharm,在creatproject那里选择新建django项目的时候,会自动帮你安装最新版的Django版本 2:进入Pycharmd的命令窗口,在下方Termina ...

  8. 下载并安装eclipse

    一. 下载eclipse 1. 进入eclipse官网——www.eclipse.org 2. 点击“DOWNLOAD”,进入下载界面 3. 点击“Download Packages”,选择所需ecl ...

  9. http与tcp

    一.基本概念 1.TCP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别” ...

  10. [易学易懂系列|rustlang语言|零基础|快速入门|(7)|函数Functions与闭包Closure]

    [易学易懂系列|rustlang语言|零基础|快速入门|(7)函数Functions与闭包Closure] 有意思的基础知识 函数Functions与闭包Closure 我们今天再来看看函数. 在Ru ...