如何允许临时的非const复制构造函数

时间:2012-01-12 18:26:29

标签: c++ const copy-constructor auto-ptr temporary-objects

如何允许带有非const引用的复制构造函数的类从临时构造中复制构造?

背景是:

我有一个函数应该返回一个指向所有从Base继承的对象的指针列表,所以我需要像vector<Base*>这样的东西。 鉴于vector<auto_ptr>不是一个选项,我想在vector<Base*>周围编写一个简单的包装器,删除其析构函数中的所有元素。

我遇到了以下问题:

我的类有一个复制构造函数如下:

auto_list(auto_list& rhs);

这样我就可以将指针列表复制到新实例并在旧实例中清除它。

但显然,这不适用于返回值,因为临时值不会绑定到非const引用。 看到auto_ptr可以从函数返回,它们是如何实现的?

注意:我不能使用C ++ 11或boost,因此不能选择移动语义或unique_ptr。

如果有帮助,到目前为止这是我的代码:

template <typename T> class auto_list
{
private:

    vector<T*> pointers;

public:

    auto_list(vector<T*>& pointers)
    {
        this->pointers = pointers;
    }

    auto_list(auto_list& rhs)
    {
        this->pointers = rhs.pointers;
        rhs.pointers.clear();
    }

    ~auto_list()
    {
        for(typename vector<T*>::const_iterator it = this->pointers.begin(); it != this->pointers.end(); it++)
        {
            delete (*it);
        }
    }

    auto_list& operator=(auto_list& rhs)
    {
        this->pointers = rhs.pointers;
        rhs.pointers.clear();
    }

    vector<T*> get_pointers() const
    {
        return this->pointers;
    }
};

4 个答案:

答案 0 :(得分:3)

这个类使用起来相当混乱,就像auto_ptr本身一样,我敦促你使用更明智的智能指针。即使你有充分的理由不使用Boost(对于我的生活,我也不能想到为什么不这样做),std::tr1::shared_ptr怎么样?

如果您决定继续学习本课程,那么auto_ptr通过在类(auto_ptr_ref)中包装引用来解决从临时初始化的问题。包装器由*this的转换函数创建(它是一个左值,因此可以绑定到非const引用),然后可以通过值传递给构造函数。

你可以做类似的事情:

template <typename T> class auto_list_ref
{
    friend class auto_list<T>;
    auto_list_ref(auto_list<T> & ref) : ref(ref) {}
    auto_list<T> & ref;
};

template <typename T> class auto_list
{
public:
    // Add a constructor and conversion operator as follows:

    auto_list(auto_list_ref<T> rhs)
    {
        this->pointers = rhs.ref.pointers;
        rhs.ref.pointers.clear();
    }

    operator auto_list_ref<T>() {return auto_list_ref<T>(*this);}
};

Here is a demonstration.

答案 1 :(得分:2)

发明rvalue引用的全部原因是因为这在C ++ 03中不起作用。我的意思是,从根本上说,彻底地,破碎了。你正试图打击一些无法做到的事情。坚持传递返回值或堆分配指针。

答案 2 :(得分:1)

您可以将pointers声明为mutable,从而允许您声明您的副本ctor和作业操作为const auto_list &并仍然清除。但是,您需要仔细使用生成的类,因为任何副本都将清除从中复制的对象。

答案 3 :(得分:0)

如果您正在解决缺少std::vector<auto_ptr<Base>>和auto_list的问题,我建议您完全放弃课程并编写自己的计数指针,这些指针适用于std::vector。如果您只需要存储Base的常用对象,您甚至可以对它进行引用计数,因此代码将小于您当前正在编写的自定义列表。

如果这不起作用,那么你的第二个最佳选择可能是在C ++ 11之前采用标准处理unique_ptr<>的破解方式。即传递const reference并对其进行const_cast(哎呀!!!)。如果你决定这一点,那就非常非常小心地在任何时候都能正确地获得语义(它们将被const不足的东西打破)。