2016-07-28 6 views
1

У меня есть класс, который имеет член const vector, который содержит уникальные указатели на некоторые объекты. При построении объект sequence должен украсть собственность на вектор уникальных указателей, передаваемых конструктору, чтобы объект последовательности теперь стал владельцем объектов, принадлежащих уникальным указателям в векторном параметре.C++ Embded lambda в списке инициализаторов для члена const vector

class sequence 
{ 
    const std::vector< std::unique_ptr<statement> > m_statements; 

    sequence(std::vector< std::unique_ptr<statement> > & statements); 
}; 

Первый раз, когда я пытался реализовать конструктор, я сделал следующее:

sequence::sequence(vector< unique_ptr<statement> > & statements) 
    m_statements(statements) 
{ 
} 

Но, конечно, это не компилируется, так как один не может копировать построить unique_ptr и, таким образом, может» t copy-construct a vector.

C++ не позволяет инициализировать члены const в теле конструктора (например, Java с конечными членами), но только в списке инициализаторов. Таким образом, одним из возможных решений могло бы быть удаление модификатора constm_statement и, используя цикл, переместить содержимое из одного вектора в другое в теле конструктора.

Но я хочу сохранить этот const модификатор.

Итак, я придумал другое решение, которое, похоже, компилируется, но поскольку я новичок в C++ 11, я не уверен в том, что он делает exacly. Идея заключалась в том, чтобы включить описанный выше цикл в лямбда-функцию, чтобы я мог инициализировать m_statement в списке инициализаторов с использованием цикла и по-прежнему сохранять модификатор const на m_statement.

sequence::sequence(vector< unique_ptr< const statement > > & statements) : 
    m_statements(([ & statements ] { 
     vector< unique_ptr< const statement > > copied_vec; 
     for(auto & stm : statements) 
      copied_vec.push_back(move(stm)); 
     return copied_vec; 
    })()) 
{ 
} 

Это компилируется. Но я не уверен, что происходит, начиная с оператора возврата функции лямбда.

Я предполагаю, что копия copied_vec создана и возвращена. Что происходит, когда вы возвращаете по значению вектор уникальных указателей? Это правильный способ делать то, что я хочу, несмотря на то, что это странно, или я должен просто отказаться от модификатора const на m_statetent? Спасибо.

+1

Не отвечает на вопрос о том, как ваш код работает, но [это] (http://stackoverflow.com/questions/18282204/proper-way-of-transferring-ownership-of-a-stdvector- stdunique-ptr-int-t) показывает вам правильный способ «переместить» вектор. – NathanOliver

+0

Вы создаете лямбду, а затем называете ее. Умный, хотя и ненужный. – lorro

+0

@NathanOliver Спасибо. Я потерял дар речи, чтобы понять, насколько это просто. – Virus721

ответ

6

У меня отсутствует причина, почему конструктор перемещения не может быть использован?

sequence::sequence(vector< unique_ptr<statement> > && statements) 
    m_statements(std::move(statements)) 
{ 
} 
+0

Спасибо за помощь. Я просто об этом не думал. Хотя мне все равно хотелось бы знать, что происходит, когда я копирую 'copied_vec', используя возврат по значению. – Virus721

+0

В зависимости от «деталей», я думаю, вы, вероятно, получите какую-то форму RVO. Я думаю, что с C++ 17 это даже предусмотрено (опять же, в зависимости от деталей). – KayEss

+0

Спасибо. Но игнорируя такую ​​неявную оптимизацию компилятора, что происходит, когда вы копируете вектор уникальных указателей? Владение передается от указателей исходного вектора к указателям вновь созданного вектора? – Virus721