实现智能指针 - 在向量中存储模板类

发布于 2024-08-02 19:50:24 字数 1689 浏览 5 评论 0 原文

我在将智能指针的实例存储到容器中时遇到问题。这是指针的代码。

#include "std_lib_facilities.h"

template <class T>
class counted_ptr{
private:
    T* pointer;
    int* count;

public:
    counted_ptr(T* p = 0, int* c = new int(1)) : pointer(p), count(c) {}    // default constructor
    explicit counted_ptr(const counted_ptr& p) : pointer(p.pointer), count(p.count) { ++*count; } // copy constructor
    ~counted_ptr()
    {
        --*count;
        if(!*count) {
            delete pointer;
            delete count;
        }
    }

    counted_ptr& operator=(const counted_ptr& p)    // copy assignment
    {
        pointer = p.pointer;
        count = p.count;
        ++*count;
        return *this;
    }
    T* operator->() const{ return pointer; }
    T& operator*() const { return *pointer; }
    int& operator[](int index) { return pointer[index]; }

    int Get_count() const { return *count; }    // public accessor for count


};




int main()
{
    counted_ptr<double>one;
    counted_ptr<double>two(one);
    one = new double(5);
    vector<counted_ptr<double> >test;
}

在 int main() 中,向量 > 行确实可以编译。当我第一次尝试使用 vector 时, > 它没有编译(可能是因为它缺少参数。)但是,当我尝试使用 Push_back 时,例如

test.push_back(one);

我收到一个编译器错误,该错误打开了 vector.tcc,并显示特定错误,指出

no matching function for call to `counted_ptr<double>::counted_ptr(const counted_ptr<double>&)'|

我是猜测push_back找不到counted_ptr,但我真的不确定。任何 感谢帮助,谢谢。

编辑:但是,这有效。测试[0] = 1;我猜想 Push_back 的语义是限制它的原因。

I'm having trouble storing instances of my smart pointer into a container. Here is the code for the pointer.

#include "std_lib_facilities.h"

template <class T>
class counted_ptr{
private:
    T* pointer;
    int* count;

public:
    counted_ptr(T* p = 0, int* c = new int(1)) : pointer(p), count(c) {}    // default constructor
    explicit counted_ptr(const counted_ptr& p) : pointer(p.pointer), count(p.count) { ++*count; } // copy constructor
    ~counted_ptr()
    {
        --*count;
        if(!*count) {
            delete pointer;
            delete count;
        }
    }

    counted_ptr& operator=(const counted_ptr& p)    // copy assignment
    {
        pointer = p.pointer;
        count = p.count;
        ++*count;
        return *this;
    }
    T* operator->() const{ return pointer; }
    T& operator*() const { return *pointer; }
    int& operator[](int index) { return pointer[index]; }

    int Get_count() const { return *count; }    // public accessor for count


};




int main()
{
    counted_ptr<double>one;
    counted_ptr<double>two(one);
    one = new double(5);
    vector<counted_ptr<double> >test;
}

In int main(), the vector<counted_ptr<double> > line does compile. When I first tried it with just vector<counted_ptr<double> > it didn't compile (probably because it was lacking parameters.) However, when I try to use push_back such as

test.push_back(one);

I get a compiler error that opens up vector.tcc with the specific error saying that

no matching function for call to `counted_ptr<double>::counted_ptr(const counted_ptr<double>&)'|

I'm guessing that push_back can't find a counted_ptr, but I'm really not sure. Any
help is appreciated, thanks.

Edit: However, this works. test[0] = one; I guess the semantics of push_back are what is restricting it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

花开浅夏 2024-08-09 19:50:24

您可能想尝试一下:

test.push_back(counted_ptr<double>(one));

复制构造函数是显式的,这意味着编译器不会隐式调用它。

就我个人而言,我会让原始指针构造函数显式,而复制构造函数不显式。这将更接近平常的行为。

编辑:我还建议您实现交换方法。它使分配变得绝对微不足道。你最终会得到这样的结果:

counted_ptr &operator=(const counted_ptr &rhs) {
    counted_ptr(rhs).swap(*this);
    return *this;
}

这也有一个好处,就是所有的会计发生在构造函数/析构函数中,这更容易管理:-)。

You may want to try this:

test.push_back(counted_ptr<double>(one));

You copy constructor is explicit which means that the compiler won't implicitly invoke it.

Personally, I would make the raw pointer constructor explicit and the copy ctor not explicit. That would be closer to usual behavior.

EDIT: I also recommend that you implement a swap method. It makes assignment absolutely trivial. You end up with something like this:

counted_ptr &operator=(const counted_ptr &rhs) {
    counted_ptr(rhs).swap(*this);
    return *this;
}

This also has the benefit of all of the accounting happening in constructors/destructors which is a lot simpler to manage :-).

や莫失莫忘 2024-08-09 19:50:24

您的赋值运算符是错误的。
它所指向的物体发生了什么?
如果您分配给自​​己或同一个内部对象,会发生什么?

counted_ptr& operator=(const counted_ptr& p)    // copy assignment
{
    if (&p != this)
    {
        --*count;
        if ((*count) == 0) // Much more readable than !*count
        {
            delete pointer;
            delete count;
        }
        pointer = p.pointer;
        count = p.count;
        ++*count;
    }
    return *this;
}

注意:编写自己的智能指针并不是一个好主意。
它们并不像您想象的那么容易写。

注:这是我发现的第一件事。可能还有更多,我不确定这是否 100% 正确。

事实上,我会更改赋值运算符以使用复制/交换 idium。

counted_ptr& operator=(const counted_ptr& p)    // copy assignment
{
    counted_ptr<T>     tmp(p);   // increment counter on p
    swap(tmp.pointer, pointer);
    swap(tmp.count    count);

    return *this;
                                 // tmp goes out of scope and thus the
                                 // destructor gets called and what was in this
                                 // object is now destroyed correctly.
}
// It may even be worth writing your own swap operator.
// Make sure you declare it as no-throw and grantee it.

Your assignment operator is wrong.
What happened to the object it was pointing at?
What happens if you are assigning to yourself or the same internal object?

counted_ptr& operator=(const counted_ptr& p)    // copy assignment
{
    if (&p != this)
    {
        --*count;
        if ((*count) == 0) // Much more readable than !*count
        {
            delete pointer;
            delete count;
        }
        pointer = p.pointer;
        count = p.count;
        ++*count;
    }
    return *this;
}

Note: Writing your own smart pointer is not a good idea.
They are not as trivial to write as you think.

Note: This is the first thing I spotted. There could be more, and I am not sure this is 100% correct.

In fact I would change the assignment operator to use copy/swap idium.

counted_ptr& operator=(const counted_ptr& p)    // copy assignment
{
    counted_ptr<T>     tmp(p);   // increment counter on p
    swap(tmp.pointer, pointer);
    swap(tmp.count    count);

    return *this;
                                 // tmp goes out of scope and thus the
                                 // destructor gets called and what was in this
                                 // object is now destroyed correctly.
}
// It may even be worth writing your own swap operator.
// Make sure you declare it as no-throw and grantee it.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文