简体   繁体   English

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

[英]How to allow non-const copy constructor for temporaries

How do I allow a class with a copy constructor that takes a non-const reference to be copy-constructed from temporaries? 我该如何允许具有复制构造函数且使用非常量引用的类从临时对象进行复制构造?

The background is this: 背景是这样的:

I have a function that should return a list of pointers to objects that all inherit from Base, so I need something like vector<Base*> . 我有一个函数,该函数应该返回一个指针列表,这些指针都从Base继承,所以我需要诸如vector<Base*>类的东西。 Given that vector<auto_ptr> is not much of an option, I wanted to write a simple wrapper around vector<Base*> that deletes all elements in its destructor. 鉴于vector<auto_ptr>不是很多选择,我想为vector<Base*>编写一个简单的包装程序,以删除其析构函数中的所有元素。

I'm facing the following problem: 我面临以下问题:

My class has a copy constructor as follows: 我的课有一个复制构造函数,如下所示:

auto_list(auto_list& rhs);

so that I can copy the pointer list to the new instance and clear it in the old one. 这样我就可以将指针列表复制到新实例,并在旧实例中清除它。

But obviously, that won't work with return values because temporaries don't bind to a non-const reference. 但是显然,这对返回值不起作用,因为临时对象不会绑定到非const引用。 Seeing that auto_ptr can be returned from functions, how did they implement it? 看到auto_ptr可以从函数中返回,它们是如何实现的?

Note: I can't use C++11 or boost, so move semantics or unique_ptr are not an option. 注意:我不能使用C ++ 11或boost,因此,不能使用move语义或unique_ptr。

If it helps, this is my code so far: 如果有帮助,到目前为止,这是我的代码:

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;
    }
};

This class will be rather confusing to use, just as auto_ptr itself, and I urge you to use more sensible smart pointers. 就像auto_ptr本身一样,该类的使用非常混乱,我敦促您使用更明智的智能指针。 Even if you do have a good reason for not using Boost (and for the life of me I can't think why not), how about std::tr1::shared_ptr ? 即使您确实有一个不使用Boost的充分理由(对于我的一生,我也无法想到为什么不这样做), std::tr1::shared_ptr呢?

If you're determined to pursue this course, then auto_ptr solves the problem of initialising from a temporary by wrapping a reference in a class ( auto_ptr_ref ). 如果您决定继续学习此课程,那么auto_ptr可以通过将引用包装在类( auto_ptr_ref )中来解决从临时初始化的问题。 The wrapper is created by a conversion function from *this (which is an lvalue, and therefore can be bound to a non-const reference), and can then be passed by value to a constructor. 包装器由*this的转换函数创建(它是一个左值,因此可以绑定到非const引用),然后可以按值将其传递给构造函数。

You can do something similar: 您可以执行类似的操作:

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. 这是一个示范。

The whole reason that rvalue references were invented was because this cannot work in C++03. 发明右值引用的全部原因是因为它不能在C ++ 03中工作。 I mean, fundamentally, utterly, broken. 我的意思是,从根本上说,完全是破裂的。 You are trying to fight something that cannot be done. 您正在尝试解决一些无法完成的事情。 Stick to passing in return values or heap-allocated pointers. 坚持传递返回值或堆分配的指针。

You could declare pointers as mutable , thus allowing you to declare your copy ctor and assignment ops as taking const auto_list & and still call clear. 您可以将pointers声明为mutable ,从而允许您将副本ctor和赋值操作声明为const auto_list &并仍然调用clear。 You need to use the resulting class carefully, however, as any copy will clear the object copied from. 但是,您需要谨慎使用结果类,因为任何副本都会清除从中复制的对象。

If you are just working around the lack of std::vector<auto_ptr<Base>> with your auto_list, I suggest, you drop the class altogether and write your own counted pointers, which work with std::vector . 如果您只是通过auto_list解决std::vector<auto_ptr<Base>>的问题,我建议您完全删除该类,并编写自己的计数指针,该指针可用于std::vector If all you need is to store common objects of Base , you can even make it reference counted, so the code will be less than the custom list you are currently writing. 如果您只需要存储Base公共对象,则甚至可以将其引用计数,因此该代码将少于您当前正在编写的自定义列表。

If this does not work, your second best choice probably is to adopt the broken way the standard handled unique_ptr<> before C++11. 如果这不起作用,您的第二个最佳选择可能是采用标准的方法在C ++ 11之前处理unique_ptr<> Ie pass in a const reference and do a const_cast on it (yuck!!!). 即传递一个const reference并对其进行const_cast (糟糕!)。 If you decide this, be very very very carefull to get the semantics right at all times (they will be broken enough by const things not being const). 如果您决定这样做,请非常非常谨慎地始终确保正确的语义(由于const事物不是const,它们将被破坏得足够多)。

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

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