2016-03-07 4 views
0

У меня есть std::vector<std::unique_ptr<T>> vec1, где T - абстрактный тип. Я хотел бы создать std::vector<T*> vec2, где объекты, указываемые указателями со второго вектора, являются копией объектов, на которые указывают указатели 1-го вектора.Как скопировать вектор <unique_ptr <T>> на независимый вектор <T*>

Так, например: *(vec1[0]) == *(vec2[0]) и vec1[0].get() != vec2[0] ... и т.д. ...

Как сделать это?

+0

Что именно проблема? Вы не знаете, как получить базовый указатель от 'unique_ptr'? Или что-то другое? – SergeyA

+0

@SergeyA. Я знаю, что горячий, чтобы получить необработанный указатель из 'std :: unique_ptr' (метод' get() '). Но если я нажму на vec2, то vec2 не будет независим от vec1. Указатели из vec1 указывают на то же место в памяти, что и указатели от vec2. Мне нужна копия объектов. – peter55555

+0

Зачем? Это огромный запах кода. C API принимает 'T **' и право собственности? :( –

ответ

5

Использование std::transform

std::vector<T*> vec2; 
vec2.reserve(vec1.size()); // optimization to avoid reallocations, it isn't necessary, and without it the code still works correctly 
std::transform(vec1.begin(), vec1.end(), std::back_inserter(vec2), [](const std::unique_ptr<T>& p){ return YourCloneFunction(*p); } 

Один из способов, чтобы написать клон функции, чтобы сделать все ваши классы-потомки определили виртуальную clone функцию, который является абстрактным в T. Код такого метода прост, но его необходимо определить для каждого класса Derived.

class T 
{ 
    virtual std::unique_ptr<T> clone() const = 0; 
    virtual ~T(){} 
}; 

class Derived : public T 
{ 
    std::unique_ptr<T> clone() const override { 
     return std::unique_ptr<T>(new Derived(*this)); 
    } 
}; 

При этом, код становится

std::vector<T*> vec2; 
vec2.reserve(vec1.size()); // optimization to avoid reallocations, it isn't necessary, and without it the code still works correctly 
std::transform(vec1.begin(), vec1.end(), std::back_inserter(vec2), [](const std::unique_ptr<T>& p){ return p->clone().release(); } 

Обратите внимание, что у нас есть vec2 сырые указатели, указывающие на объекты, не принадлежащие какой-либо смарт-указатель. Это плохо, если вы не пропустите vec2 в функцию устаревания, которая берет на себя ответственность за эти указатели.

В противном случае, если вы хотите только std::vector<T*> вид копии, клонировать в промежуточном std::vector<std::unique_ptr<T>>, а затем скопировать результат .get() на каждом экземпляре для std::vector<T*>

+0

, так как это копия, вы должны показать хорошее поведение, чтобы вызвать резерв правильного размера до преобразования – galop1n

+1

Почему вы обрушаете это требование? Здесь нет причин называть «резерв». – SergeyA

+3

Он работает правильно без него, это оптимизация – milleniumbug

0

Ручной способ:

std::vector<std::unique_ptr<T>> vec1; 
std::vector<T*> vec2; 
vec2.reserve(vec1.size()); // optimization to avoid reallocations 

for (const auto& e : vec1) { 
    vec2.push_back(e->clone()); 
} 

с virtual T* T::clone() const

+1

, так как это копия, вы должны показать хорошее поведение, чтобы вызвать резерв от правильного размера до петли – galop1n

+0

@ galop1n, никакой реальной необходимости. – SergeyA

+0

"* T - абстрактный тип *", что означает, что вы не можете создавать новые экземпляры 'T'. –

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

  • Нет связанных вопросов^_^