我试着写了一个自己的shared_ptr类,一个简单的类,以便更好地掌握它沿着move & copy构造函数和move & copy赋值运算符。它看起来像下面这样:
// Online C++ compiler to run C++ program online
#include <iostream>
#include <stdio.h>
template<class T>
class my_shared_ptr
{
private:
T* ptr = nullptr;
int* refcount = nullptr;
public:
my_shared_ptr() : ptr(nullptr),refcount(new int (0))
{std::cout <<"Inside my_shared_ptr constructor \n" ;}
my_shared_ptr(T* pT) : ptr(pT),refcount(new int (0))
{std::cout <<"Inside my_shared_ptr with pT passed in constructor \n" ;}
~my_shared_ptr()
{
std::cout <<"Inside Destructor of my_shared_ptr \n";
(*refcount)--;
std::cout <<"Inside Destructor refcount is : "<< (*refcount) <<"\n";
if((*refcount) == 0)
{
std::cout <<"Deleting the one of the ptr whose reference count is now 0 \n";
delete ptr;
}
}
// Copy constructor
my_shared_ptr(const my_shared_ptr& obj)
{
std::cout <<"Inside copy constructor call \n";
this->ptr = obj.ptr;
this->refcount = obj.refcount;
if(obj.ptr != nullptr)
{
(*this->refcount)++;
}
}
// Copy assignment operator
my_shared_ptr& operator=(const my_shared_ptr& obj)
{
std::cout <<"Inside copy assignment call \n";
if(&obj == this )
return *this;
(*this->refcount)--;
if((*this->refcount) == 0)
{
delete (this->ptr);
}
this->ptr = obj.ptr;
this->refcount = obj.refcount;
if( obj.ptr!= nullptr)
{
(*this->refcount)++;
}
return *this;
}
// Move constructor
my_shared_ptr(my_shared_ptr&& dyingobj)
{
std::cout <<"Inside move constructor call \n";
this->ptr = dyingobj.ptr;
this->refcount = dyingobj.refcount;
dyingobj.ptr = nullptr; // cleaning up the dying object
dyingobj.refcount = nullptr;
}
// Move assignment
my_shared_ptr& operator=(my_shared_ptr&& dyingobj)
{
std::cout <<"Inside move assignment call \n";
if(&dyingobj == this )
{
std::cout <<"Two objects in move assignment are equal \n";
return *this;
}
if( (this) != &dyingobj )
{
(this->refcount)--;
std::cout <<"Inside move assignment refcount is : "<< (*refcount) <<"\n";
if((this->refcount) == 0)
{
std::cout <<"Deleting the previous shared object pointer whose reference count is now 0 \n";
delete this->ptr;
}
}
this->ptr = dyingobj.ptr;
this->refcount = dyingobj.refcount;
dyingobj.ptr = nullptr; // cleaning up the dying object
dyingobj.refcount = nullptr;
return *this;
}
T* operator->() const
{
return ptr;
}
T& operator*() const
{
return *ptr;
}
};
class Resource
{
public:
Resource()
{
std::cout <<"Resource Acquired \n";
}
~Resource()
{
std::cout <<"Resource Destroyed \n";
}
};
my_shared_ptr<Resource> generateResource()
{
my_shared_ptr<Resource> res(new Resource());
return res;
}
int main()
{
std::cout <<"Before Creating mainres \n";
my_shared_ptr<Resource> mainres = generateResource();
std::cout <<"After Creating mainres \n";
mainres = generateResource();
std::cout <<"Before Creating mainres2 \n";
my_shared_ptr<Resource> mainres2 = mainres;
std::cout <<"After Creating mainres2 \n";
{
std::cout <<"Before Creating mainres3\n";
my_shared_ptr<Resource> mainres3;
mainres3 = mainres2;
std::cout <<"After mainres3 assignment\n";
}
std::cout <<"mainres3 destroyed\n";
//mainres = generateResource();
return 0;
}
上面代码的输出是:
Before Creating mainres
Resource Acquired
Inside my_shared_ptr with pT passed in constructor
After Creating mainres
Resource Acquired
Inside my_shared_ptr with pT passed in constructor
Inside move assignment call
Inside move assignment refcount is : 0
Inside Destructor of my_shared_ptr
查看O/P,似乎代码在mainres = generateResource();
之前执行良好,但之后静默退出。我没有获得任何进一步的O/P。不确定原因?纠正此问题的正确方法是什么?我哪里错了。在移动分配调用内部,我尝试删除并减少分配了不同my_shared_的my_shared_ptr对象的引用计数ptr并检查引用计数是否为0,然后删除my_shared_ptr对象的ptr。我在这里遗漏了什么吗?
先谢谢你了。
1条答案
按热度按时间kqlmhetl1#
要学习复制和移动类,如下所示总是非常有用的:
这允许你准确地跟踪输出中调用的内容。在调用之间,你应该插入更多的输出,以便能够从输出中识别出你在
main()
中的位置。如果这一部分对你来说很清楚,那么接下来你可以在SmartPointer中使用这个类来更好地理解它:
您还可以为
Verbose
类指定一个ID来跟踪各个对象。请注意,ID只能通过
rename()
函数更改!这个例子也很好地展示了解构器调用的顺序。它正好是构造顺序的相反。
下面是另一个简化的
SharedPtr
实现,它也有大量输出:如果您想对任意类型使用
SharedPtr
,您必须创建SharedPtr
和SharedState
模板。注意,这不再假设T
类型(以前的Verbose
)有一个ID。因此,它不能再显示为SharedPtr
和SharedState
的ID的一部分。这是我没有立即展示通用版本的主要原因。下面的diff显示了需要更改的地方。以minus out开头的行。以plus in开头的行。(不幸的是StackOverflow目前没有语法高亮显示)。
我还没有测试赋值运算符,如果需要调整,请告诉我!