const和shared_ptr及基于智能指针的PCL的深拷贝与浅拷贝

常量指针与指针常量

如果关键字const出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量;如果出现在星号两边,表示被指物和指针两者都是常量

//const int *ptr, int const *ptr, int * const ptr, const int * const ptr
const int* ptr1=new int(1);
int const* ptr2=new int(2);
int *const ptr3=new int(3);
const int *const ptr4=new int(4);
// error
// *ptr1=5;
// *ptr2=5;
// ptr3=ptr1;
// ok
// ptr1=ptr2;
// ptr2=ptr1;
// *ptr3=5;

const and shared_ptr

shared_ptr<T> p;             ---> T * p;                                    : nothing is const
const shared_ptr<T> p;       ---> T * const p;                              : p is const
shared_ptr<const T> p;       ---> const T * p;       <=> T const * p;       : *p is const
const shared_ptr<const T> p; ---> const T * const p; <=> T const * const p; : p and *p are const.

ConstPtr and Ptr

using Ptr = shared_ptr<PointCloud<PointT> >;
using ConstPtr = shared_ptr<const PointCloud<PointT> >;

Convert Ptr to ConstPtr

template <class T, class U>
  shared_ptr<T> const_pointer_cast (const shared_ptr<U>& sp) noexcept;

std::shared_ptr<int> foo;
std::shared_ptr<const int> bar;

foo = std::make_shared<int>(10);
bar = std::const_pointer_cast<const int>(foo);

Construct ConstPtr from Ptr

pcl::PointCloud<pcl::PointXYZRGBA>::Ptr ptr(new pcl::PointCloud<pcl::PointXYZRGBA>);
std::cout<<ptr.use_count()<<'\n';
pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr cptr(ptr);
std::cout<<ptr.use_count()<<'\n';

// [out] 1 2

智能指针

智能指针的实现

class SharedPtr
{
public:
        SharedPtr(T*ptr=NULL)
               :_ptr(ptr)
               , _pcount(new int(1))
        {}
        SharedPtr(const SharedPtr&s)
               :_ptr(s._ptr)
               , _pcount(s._pcount)
        {
               *(_pcount)++;
        }
        SharedPtr<T>&operator=(const SharedPtr&s)
        {
               if (this!= &s)
               {
                       if (--(*(this->_pcount)) == 0)
                       {
                              delete this->_ptr;
                              delete this->_pcount;
                       }
                       _ptr = s._ptr;
                       _pcount = s._pcount;
                       *(_pcount)++;
               }
               return *this;
        }
        T&operator*()
        {
               return *(this->_ptr);
        }
        T*operator->()
        {
               return this->_ptr;
        }
        ~SharedPtr()
        {
               --(*(this->_pcount));
               if (this->_pcount == 0)
               {
                       delete _ptr;
                       _ptr = NULL;
                       delete _pcount;
                       _pcount = NULL;
               }
        }
private:
        T*_ptr;
        int *_pcount;//指向引用计数的指针
};
int main()
{
        SharedPtr<int>p1(new int(1));
        SharedPtr<int>p2(p1);//调用拷贝构造函数
        SharedPtr<int> p3 = p2;//调用的是拷贝构造函数、因为p3原本是不存在的。
        p3 = p2;
        system("pause");
        return 0;
}

注意拷贝构造函数和operator=调用时机的区别,当对象不存在时,调用的是拷贝构造函数,当对象存在时,调用的是operator=

智能指针调用示例

pcl::PointCloud<pcl::PointXYZRGBA>::Ptr glbptr(new pcl::PointCloud<pcl::PointXYZRGBA>);

// It cannot be acheived if you want to encapsulate the Ptr object 
// 返回的是全局变量的引用,不会出现拷贝
const pcl::PointCloud<pcl::PointXYZRGBA>::Ptr& get(){
    return glbptr;
}
// 由Ptr构造生成ConstPtr,ConstPtr对象构造会出现复制
pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr getConst(){
    return std::const_pointer_cast<const pcl::PointCloud<pcl::PointXYZRGBA> >(glbptr);
}

bool bvisualizer=true;

int main ()
{
    get()->points.resize(1); // ok to operate the object
    std::cout<<glbptr.use_count()<<'\n';
    // 等价于pcl::PointCloud<pcl::PointXYZRGBA>::Ptr glbptr1 = glbptr, 由于拷贝构造,出现复制
    pcl::PointCloud<pcl::PointXYZRGBA>::Ptr glbptr1=get();  
    glbptr1->points.resize(2); // ok to operate the object
    std::cout<<glbptr.use_count()<<'\n';
    pcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr cglbptr2=getConst();
    std::cout<<glbptr.use_count()<<'\n';
    std::cout<<glbptr->points.size()<<'\n';
}
# [output]
1
2
3
2

基于智能指针的PCL深拷贝与浅拷贝

测试用例来源:测试用例

typedef pcl::PointXYZ MyPoint;
typedef pcl::PointCloud<MyPoint> MyPointCloud;

void func_ptr(MyPointCloud::Ptr pc){
    pc->resize(0);
}

void func_pointcloud(MyPointCloud pc){
    pc.resize(0);
}

void func_ref(MyPointCloud& pc){
    pc.resize(10);
}

MyPointCloud::Ptr pc (new MyPointCloud()), pc2(new MyPointCloud());
MyPointCloud pc3, pc4;
string filename = "/home/zhao/Downloads/csdn_codes-main/pointcloud_copy/mesh.pcd";

用例1:测试上述函数智能指针拷贝传参、值传参和引用传参

pcl::io::loadPCDFile<MyPoint>(filename, *pc);

cout << "------- Test 1. Using Ptr" << endl;
cout<<"before: "<< (*pc).size() << endl;
func_ptr(pc);
cout << "after: " << (*pc).size() << endl;

pcl::io::loadPCDFile<MyPoint>(filename, *pc);
cout << "------- Test 2.1 Using pointcloud but input *ptr" << endl;
cout<<"before: "<< (*pc).size() << endl;
func_pointcloud(*pc);
cout << "after: " << (*pc).size() << endl;

pcl::io::loadPCDFile<MyPoint>(filename, pc3);
cout << "------- Test 2.2 Using pointcloud but input pointcloud" << endl;
cout<<"before: "<< pc3.size() << endl;
func_pointcloud(pc3);
cout << "after: " << pc3.size() << endl;

pcl::io::loadPCDFile<MyPoint>(filename, pc3);
pcl::io::loadPCDFile<MyPoint>(filename, *pc);
cout << "------- Test 3. Using ref pointcloud" << endl;
cout<<"before: "<< (*pc).size() << endl;
func_ref(*pc);
cout << "after: " << (*pc).size() << endl;
cout<<"before: "<< pc3.size() << endl;
func_ref(pc3);
cout << "after: " << pc3.size() << endl;

输出

------- Test 1. Using Ptr
before: 12500
after: 0
------- Test 2.1 Using pointcloud but input *ptr
before: 12500
after: 12500
------- Test 2.2 Using pointcloud but input pointcloud
before: 12500
after: 12500
------- Test 3. Using ref pointcloud
before: 12500
after: 10
before: 12500
after: 10

根据智能指针的operator*操作,*ptr对应的就是值的引用,上述的操作结果很好理解

用例2:智能指针的operator=

pcl::io::loadPCDFile<MyPoint>(filename, *pc);
pc2 = pc;
cout << "Pc2: " << pc2->size() << endl;
pc->resize(0);
cout << "Pc2: " << pc2->size() << endl;
// ---
// Pc2: 12500
// Pc2: 0

pc2 = pc;调用的是shared_ptr的operator=函数,由实现可知pc2和pc指向同一块内存地址,所以操作相互影响,若在这之后调用pcl深拷贝,由于两者指向的是同一地址,所以copyPointCloud后,两者仍相互影响

pcl::copyPointCloud(*pc, *pc2);
cout << "pc2: " << pc2->size() << endl;
pc->resize(0);
cout << "pc2: " << pc2->size() << endl;
// ---
// pc2: 12500
// pc2: 0

用例3:调用copyPointCloud
根据copyPointCloud的实现,其输入src和dst都必须先被分配内存

cout << "================  Copy Function test ================" << endl;
cout << "------- Test 1. Copy *pointer to *pointer" << endl;
pcl::io::loadPCDFile<MyPoint>(filename, *pc);
pcl::copyPointCloud(*pc, *pc2);
cout << "pc2: " << pc2->size() << endl;
pc->resize(0);
cout << "pc2: " << pc2->size() << endl;

cout << "------- Test 2. Copy *pointer to value" << endl;
pcl::io::loadPCDFile<MyPoint>(filename, *pc);
pcl::copyPointCloud(*pc, pc3);
cout << "pc3: " << pc3.size() << endl;
pc->resize(0);
cout << "pc3: " << pc3.size() << endl;

cout << "------- Test 3. Copy value to *pointer" << endl;
pcl::io::loadPCDFile<MyPoint>(filename, pc3);
pcl::copyPointCloud(pc3, *pc);
cout << "pc: " << pc->size() << endl;
pc3.resize(0);
cout << "pc: " << pc->size() << endl;

cout << "------- Test 4. Copy value to value" << endl;
pcl::io::loadPCDFile<MyPoint>(filename, pc3);
pcl::copyPointCloud(pc3, pc4);
cout << "pc4: " << pc4.size() << endl;
pc3.resize(0);
cout << "pc4: " << pc4.size() << endl;
================  Copy Function test ================
------- Test 1. Copy *pointer to *pointer
pc2: 12500
pc2: 12500
------- Test 2. Copy *pointer to value
pc3: 12500
pc3: 12500
------- Test 3. Copy value to *pointer
pc: 12500
pc: 12500
------- Test 4. Copy value to value
pc4: 12500
pc4: 12500

可见copyPointCloud实现的是深拷贝
用例4:PointCloud的operator=
在PointCloud源码中并未单独实现operator=操作,采用默认操作,使用值引用,故为两块内存,互补干扰

cout << "------- Test 2. Copy *pointer to *pointer" << endl;
pcl::io::loadPCDFile<MyPoint>(filename, *pc);
*pc2 = *pc;
cout << "Pc2: " << pc2->size() << endl;
pc->resize(0);
cout << "Pc2: " << pc2->size() << endl;

cout << "------- Test 3. Copy *pointer to value" << endl;
pcl::io::loadPCDFile<MyPoint>(filename, *pc);
pc3 = *pc;
cout << "Pc3: " << pc3.size() << endl;
pc->resize(0);
cout << "Pc3: " << pc3.size() << endl;


cout << "------- Test 4. Copy value to value" << endl;
pcl::io::loadPCDFile<MyPoint>(filename, pc3);
pc4 = pc3;
cout << "Pc4: " << pc3.size() << endl;
pc4.resize(0);
cout << "Pc4: " << pc3.size() << endl;

cout << "------- Test 5. Copy value to *pointer" << endl;
pcl::io::loadPCDFile<MyPoint>(filename, pc3);
*pc = pc3;
cout << "Pc: " << pc->size() << endl;
pc3.resize(0);
cout << "Pc: " << pc->size() << endl;
------- Test 2. Copy *pointer to *pointer
Pc2: 12500
Pc2: 12500
------- Test 3. Copy *pointer to value
Pc3: 12500
Pc3: 12500
------- Test 4. Copy value to value
Pc4: 12500
Pc4: 12500
------- Test 5. Copy value to *pointer
Pc: 12500
Pc: 12500

结果支撑上述结论

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值