c++ - 作为类成员管理指针 vector

标签 c++ pointers vector

我处于一种相当特殊的情况,需要我使用原始指针 vector 作为类成员:

这是我需要的基本示例:

#include <vector>

class Foo
{
    virtual void foo() {}
};

class Bar : public Foo
{
    void foo(){}
};

class FooBar
{
    vector<Foo*> list;
    void add(){ list.push_back(new Bar()); }
};

来自Java,我非常害怕指针和内存泄漏。 This post最初建议当对象超出范围时手动删除对象。在 FooBar 的析构函数中执行此操作是否足够?

class FooBar
{
    vector<Foo*> list;
    void add(){ list.push_back(new Bar()); }

    ~FooBar(){
         for(vector<Foo*>::iterator it=list.begin(); it!=list.end(); it++)
             delete *it;
    }

};

rule of three ,我想我还必须实现一个复制构造函数和一个赋值运算符。以下内容(基于 thisthat 帖子)是正确的实现吗?

FooBar::FooBar(const FooBar& orig) : list(orig.list.size()) {
    try {
        vector<Foo*>::iterator thisit = list.begin();
        vector<Foo*>::const_iterator thatit = orig.list.cbegin();

        for (; thatit != orig.list.cend(); ++thisit, ++thatit)
            *thisit = *thatit;  // I'm okay with a shallow copy

    } catch (...) {
        for (vector<Foo*>::iterator i = list.begin(); i != list.end(); ++i)
            if (!*i)
                break;
            else
                delete *i;

        throw;
    }
}

FooBar& operator=(const FooBar& orig){
    FooBar tmp(orig);
    swap(tmp);
    return *this;
}

最佳答案

据我所知,您的代码存在一些重大缺陷。首先,您的第一个代码是正确的,是的,只要您的类拥有对象并且不被复制,您的析构函数就会执行它应该执行的操作。

此外,您的复制构造函数和赋值运算符看起来有问题。首先,如果您可以接受浅复制,那么您甚至不必编写函数,std::vector 的复制构造函数和赋值运算符无论如何都会完成您手动完成的操作。我认为你不需要那个 try-catch block 。顺便问一下,赋值运算符中的交换的实现在哪里?

为了您的目的,一个非常小的引用计数方案就可以工作:

class FooPtr
{
     Foo* _raw;
     size_t* _ctl;

     FooPtr(Foo* ptr) : 
         _raw(ptr), _ctl(new size_t(0))
     {
     }

     template <class T>
     FooPtr(T* ptr) : FooPtr(static_cast<Foo*>(ptr)) {}

     FooPtr(const FooPtr& rhs) : 
         _raw(rhs._raw), _ctl(rhs._ctl)
     {
         ++(*_ctl);
     }

     ~FooPtr()
     {
        if (_raw == nullptr) return;
        --(*_ctl);
        if (*_ctl == 0)
        {
            delete _raw;
            delete _ctl;
        }
     }

     FooPtr& operator=(FooPtr ptr)
     {
         std::swap(*this, ptr);
         return *this;
     }

     Foo* operator->()
     {
         return _raw;
     }

     Foo& operator*()
     {
         return *_raw;
     }
}

你的类现在看起来像这样,不需要析构函数、复制构造函数或赋值运算符:

class FooBar
{
     vector<FooPtr> list;
     void add(){ list.emplace_back(new Bar()); }
}

我写得很快,它可能包含错误,尽管它为您提供了我认为的基本想法。另外,我还使用了一些 C++11 功能,例如 emplace_backnullptr,但它们可以轻松地转换为非 11 代码。

关于c++ - 作为类成员管理指针 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35937148/

相关文章:

c++ - 将引用显式传递到不期望引用的函数模板中会导致问题吗?

c++ - 一个函数检测参数类型,值,以及另一个函数的名称和返回值?

c++ - 数组上的指针运算

c - GTK+/C : Passing data through g_signal_connect changes the data

C++ Vector 内容被删除?

c++ - 如何制作干净的clang前端?

c - 将 Char 数组附加到 Char 指针

java - 写入具有 Vector 属性的对象时出现 java.io.NotSerializedException

javascript - 在 javascript 中向 CanvasRenderingContext2D 添加标记

c++ - 对数组的元素编号感到困惑是-1