2012-01-12 3 views
0

Как разрешить класс с конструктором копирования, который принимает неконстантную ссылку для копирования из временных страниц?Как разрешить конструктор константной копии для временных рядов

Предпосылки это:

У меня есть функция, которая должна возвращать список указателей на объекты, которые все наследуемые из базы, так что мне нужно что-то вроде vector<Base*>. Учитывая, что vector<auto_ptr> не очень-то вариант, я хотел написать простую оболочку вокруг vector<Base*>, которая удаляет все элементы в своем деструкторе.

Я столкнулся со следующей проблемой:

Мой класс имеет конструктор копирования следующим образом:

auto_list(auto_list& rhs); 

так, что я могу скопировать список указателей на новый экземпляр и очистить его в старом один.

Но, очевидно, что это не будет работать с возвращаемыми значениями, потому что временные файлы не привязываются к неконстантной ссылке. Видя, что 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; 
    } 
}; 

ответ

3

Этот класс будет довольно запутанным, так же как и auto_ptr, и я настоятельно призываю вас использовать более разумные интеллектуальные указатели. Даже если у вас есть веская причина не использовать Boost (и для жизни меня не могу понять, почему нет), как насчет std::tr1::shared_ptr?

Если вы решили продолжить этот курс, то auto_ptr решает проблему инициализации из временного путем переноса ссылки в класс (auto_ptr_ref).Оболочка создается с помощью функции преобразования от *this (которая является значением lvalue и поэтому может быть привязана к неконстантной ссылке) и затем может передаваться по значению конструктору.

Вы можете сделать что-то подобное:

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.

2

Вся причина, по которой RValue ссылки были изобретены потому, что это не может работать в C++ 03. Я имею в виду, принципиально, совершенно, сломанный. Вы пытаетесь бороться с чем-то, чего нельзя сделать. Придерживайтесь передачи в возвращаемых значениях или указателей, выделенных кучей.

1

Вы можете объявить pointers как mutable, что позволит вам объявить вашу копию ctor и присваивание ops как принимающей const auto_list & и до сих пор вызывать ясность. Однако вам необходимо использовать полученный класс, так как любая копия очистит объект, скопированный с.

+0

Это кажется довольно простой исправить на самом деле. Есть ли что-то, что может взорваться? Увидев ответ Майка Сеймура, мне интересно, почему auto_ptr усложняет подобные вещи вместо использования mutable. – pezcode

+0

Тогда вы больше не сможете объявить его 'const' для предотвращения недействительности, что сделает его еще более запутанным и подверженным ошибкам, чем' auto_ptr'. Это может быть признано недействительным, передав его * любой * функции, даже если функция принимает ссылку 'const'. –

0

Если вы просто работаете вокруг отсутствияс вашим автосообществом, я предлагаю вам полностью отказаться от класса и написать собственные подсчитанные указатели, которые работают с std::vector. Если вам нужно хранить общие объекты Base, вы даже можете сделать подсчет этой ссылки, поэтому код будет меньше, чем пользовательский список, который вы сейчас пишете.

Если это не сработает, вторым вариантом, вероятно, является принятие сломанного способа стандартного обработанного unique_ptr<> до C++ 11. То есть перейдите в const reference и сделайте const_cast на нем (yuck !!!). Если вы решите это, будьте очень осторожны, чтобы получить семантику в любое время (они будут достаточно разбиты, если const не будет const).

Смежные вопросы