PCL智能指针疑云 <三> 智能指针作为函数的传值参数和传引用参数
一
函数的参数传递可以简单分类为“传值”和“传引用”。
声明函数时,形参带引用“&”,则函数调用时,是把实参所在的内存直接传给函数所开辟的栈内存。在函数内对形参的修改相当于对实参也进行修改。
声明函数时,形参不带引用,则函数调用时,是把实参拷贝一份作为形参。从内存上看,存在两个存放相同变量的区域,分别是实参和形参。在函数中对形参的修改,都不会对实参产生影响。函数退出后,形参所在的栈内存全部销毁。
二
对智能指针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智能指针疑云 <三> 智能指针作为函数的传值参数和传引用参数的更多相关文章
- c指针点滴三(指针运算)
#include <stdio.h> #include <stdlib.h> void main3() { ; int *p = # p++;//不可预测的值 ...
- C和指针 第三章 指针常量与常量指针
c语言中声明常量的两种方式 const int value int const value 如果要声明常量的指针,即指向常量的指针,则可以参考上面的常量声明修改一下 const int *ptr in ...
- C语言指针(三)指针传递给函数
实例1:传递一个无符号的long型指针给该函数 #include<stdio.h>#include<time.h>void getSeconds(unsignedlong*pa ...
- 指针数组与带参main函数
(一)指针数组 指针数组就是每一个元素存放一个地址,相当于一个指针变量.如:int *p[4]指针数组比较适合用来指向若干字符串,使得处理字符串更加灵活.例如,现在要将若干字符串按字母顺序由小到大输出 ...
- C++ 11 智能指针(shared_ptr)类成员函数详解
C++ 11 模板库的 <memory> 头文件中定义的智能指针,即 shared_ptr 模板类,用来管理指针的存储,提供有限的内存回收函数,可同时与其他对象共享该管理功能. share ...
- const 指针的三种使用方式
///////////////////////const 指针的三种状态///////////////////// 注意:const 的前后顺序 const 在类型之前 ---可以修改指针包含的地址, ...
- [C和指针]第三部分
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- iOS 认识runtime 中的三个指针 isa , IMP , SEL
runtime中函数调用经常被提及的三个概念 isa,IMP,SEL 一 isa:是类指针,之所以说isa是指针是因为Class其实是一个指向objc_class结构体的指针,而isa 是它唯一的私 ...
- C语言提高 (3) 第三天 二级指针的三种模型 栈上指针数组、栈上二维数组、堆上开辟空间
1 作业讲解 指针间接操作的三个必要条件 两个变量 其中一个是指针 建立关联:用一个指针指向另一个地址 * 简述sizeof和strlen的区别 strlen求字符串长度,字符数组到’\0’就结束 s ...
随机推荐
- PostgreSQL INSERT ON CONFLICT不存在则插入,存在则更新
近期有一个需求,向一张数据库表插入数据,如果是新数据则执行插入动作,如果插入的字段和已有字段重复,则更新该行对应的部分字段 1. 创建测试表 create table meta_data ( id s ...
- stack的常见用法
stack的常见用法 栈是什么? 栈是一种先进后出的容器 栈的定义 引入头文件 # include <stack> using namespace std; 定义栈 可以定义任何类型的栈 ...
- 01Spring基于xml的IOC配置--入门
01Spring基于xml的IOC配置 1.创建一个普通的maven工程 1.1 选择maven,不用骨架,点击下一步. 1.2 填写GroupId.ArtifactId.Version.填完点击下一 ...
- 剑指offer-5:十进制转二进制
一.二进制中‘1’的个数 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. public class Solution { public int NumberOf1(int n) { ...
- 利用sql报错帮助进行sql注入
我们可以利用sql报错帮助进行sql注入,这里以sql server 为例: sql查询时,若用group by子句时,该子句中的字段必须跟select 条件中的字段(非聚合函数)完全匹配,如果是se ...
- 生产服务器上安装Python
2018-05-17 生产环境的服务器(以下简称内网服务器)由于安全限制,可能无法连接外网.这种情况下将无法直接使用pip命令安装python的包 一.更改pip源 - 默认pip是使用Python官 ...
- Pycharm新建第一个Django项目
1:安装django 打开Pycharm,在creatproject那里选择新建django项目的时候,会自动帮你安装最新版的Django版本 2:进入Pycharmd的命令窗口,在下方Termina ...
- 下载并安装eclipse
一. 下载eclipse 1. 进入eclipse官网——www.eclipse.org 2. 点击“DOWNLOAD”,进入下载界面 3. 点击“Download Packages”,选择所需ecl ...
- http与tcp
一.基本概念 1.TCP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别” ...
- [易学易懂系列|rustlang语言|零基础|快速入门|(7)|函数Functions与闭包Closure]
[易学易懂系列|rustlang语言|零基础|快速入门|(7)函数Functions与闭包Closure] 有意思的基础知识 函数Functions与闭包Closure 我们今天再来看看函数. 在Ru ...