简体   繁体   English

复制带有模板类的构造函数未得到调用

[英]copy constructor with template class not getting called

I was trying to write a sample code for implementing shared pointer [just for practice]. 我试图编写一个示例代码来实现共享指针(仅出于练习)。 In this following example, 在以下示例中,

  • why compiler is not complaining about modifying other_T 为什么编译器不抱怨修改other_T
  • And why copy constructor SharedPtr(const T& other_T) is not getting called ? 为什么不调用复制构造函数SharedPtr(const T& other_T) Here is the code snippet. 这是代码片段。

     #include <iostream> using namespace std; #define DBG cout<<"[DEBUG]"<<__PRETTY_FUNCTION__<<endl class RefCount { protected: int m_ref; RefCount(){ DBG; m_ref = 1 ; } void reference(){ DBG; ++m_ref; } void dereference(){ DBG;--m_ref; } }; template <class T> class SharedPtr : public RefCount { T* m_T; public: SharedPtr() { DBG; m_T = new T; } SharedPtr(const T& other_T){ DBG; m_T = other_T.m_T; other_T.dereference(); other_T.m_T = NULL; } ~SharedPtr() { DBG; dereference(); cout<<m_ref<<endl; if(m_ref <= 0 && m_T != NULL ){ cout<<"Destroying"<<endl; delete m_T; m_T = NULL; } } }; class A{}; int main() { SharedPtr<A> obj; cout<<"assigning "<<endl; SharedPtr<A> obj2 = obj; cout<<"END"<<endl; return 0; } 

and the result is segfault. 结果就是段错误。

Your primary problem is that the copy constructor is being called--but you haven't defined a copy constructor, so you're getting the copy constructor that's defined by the compiler by default. 您的主要问题是,拷贝构造函数调用-但你没有定义拷贝构造函数,所以你得到年代由编译器默认定义的拷贝构造函数。

That copy constructor just does a member-wise copy. 该复制构造函数仅执行成员级复制。 That means you've allocated one A with new , then pointed two SharedPtr objects at that same A . 这意味着您已经为一个A分配了new ,然后将两个SharedPtr对象指向了该A The first one to get destroyed deletes the A object. 第一个被销毁的对象将删除A对象。 Then the second one gets destroyed, attempts to delete the same object again, and havoc ensues. 然后,第二个被销毁,尝试再次删除同一对象,并随后造成破坏。

In the end, it doesn't look to me like much (any?) of this is going to make any real difference though. 最后,在我看来,这看起来并没有多大作用(任何?)。 I'm pretty sure your basic design is broken. 我很确定您的基本设计已损坏。 To get a working shared pointer, you have one reference count and "raw" pointer to the final object. 为了获得有效的共享指针,您需要一个引用计数和指向原始对象的“原始”指针。 Then you have N SharedPtr objects referring to that one ref count/pointer structure that in turn refers to the final object. 然后,您有N个SharedPtr对象引用该引用计数/指针结构,而引用计数/指针结构又引用最终对象。

You're trying to combine the raw pointer/ref count into the individual SharedPtr, and I don't see any way that can actually work. 您正在尝试将原始指针/引用计数合并到各个SharedPtr中,但我看不到任何可行的方法。

It also seems to me that the basic concept of what you've called a RefCount is really part of the design of a SharedPtr . 在我看来,您所说的RefCount的基本概念实际上是SharedPtr设计的SharedPtr As such, I think its definition should be nested inside that of SharedPtr (and probably made private, since the outside world has no reason to know it exists, not to mention being able to access it directly). 因此,我认为它的定义应该嵌套在SharedPtr内部(并且可能是私有的,因为外界没有理由知道它的存在,更不用说能够直接访问它了)。

With those taken into account, the code might end up something like this: 考虑到这些因素,代码可能最终如下所示:

#include <iostream>
using namespace std;

#define DBG cout<<"[DEBUG]"<<__PRETTY_FUNCTION__<<endl

template <class T>
class SharedPtr {

    template <class U>
    struct Ref {
        mutable int m_ref;
        U *data;
        Ref(T *data) : m_ref(1), data(data) { DBG; }
        void add_ref() const { DBG; ++m_ref; std::cout << "m_ref=" << m_ref << "\n"; }
        void sub_ref() const { DBG; --m_ref; std::cout << "m_ref=" << m_ref << "\n"; }
        ~Ref() { delete data; }
    };

    Ref<T> *r;
public:
    SharedPtr(T *data) { DBG; r = new Ref<T>(data); }
    SharedPtr(SharedPtr const &p) : r(p.r) { DBG; r->add_ref(); }
    ~SharedPtr() {
        DBG;
        r->sub_ref();
        if (0 == r->m_ref) {
            delete r;
            std::cout << "deleted pointee\n";
        }
    }
};

class A{};

int main() {
    SharedPtr<A> obj(new A);
    cout<<"copying "<<endl;
    SharedPtr<A> obj2 = obj;
    cout<<"END"<<endl;
    return 0;
}

Notes: though this fixes at least some of the basic design, it's still quite a ways short of usable. 注意:尽管这至少修复了一些基本设计,但仍然远远不够使用。 It's missing the dereference operator, so you can't use the pointer to get to the value it points at. 它缺少解引用运算符,因此您不能使用指针获取它指向的值。 It'll break completely in a multi-threaded environment. 它会在多线程环境中完全中断。 I haven't thought enough about it to be sure, but my immediate guess is that it's probably not exception safe either. 我还没有对它进行足够的思考,但是我立即猜到它也可能不是异常安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM