2012-04-13 3 views
3

VS2010unique_ptr в структуре внутри вектора не компилировать, когда изменение размера используется в векторе

У меня есть структура, которая имеет unique_ptr внутри. Затем у меня есть vector этой структуры. Если я попытаюсь изменить размер (или использовать резерв) на вектор, я получаю ошибки компиляции. Ниже приведен урезанный пример, который все еще вызывает проблему.

struct Test 
{ 
    unique_ptr<int> pValue; 
}; 

void test() 
{ 
    // this doesn't compile 
    vector<Test> testVector; 
    testVector.resize(5); 

    // this also doesn't compile 
    testVector.reserve(5); 

    // this, of course, compiles 
    vector<unique_ptr<int>> testVector2; 
    testVector2.resize(5); 
    testVector2.reserve(5); 
} 

Ошибки я получаю жалобы по поводу доступа к закрытым членам unique_ptr (операторы присваивания). Компилятор пытается динамически построить Test &Test::operator =(const Test &) и Test::Test(const Test &). Я не понимаю, почему операция изменения размера должна вызвать любую из этих функций (почему бы ей не вызвать конструктор по умолчанию, если это необходимо?). Оба они представляют проблемы, потому что невозможно сделать либо unique_ptr из-за const.

ответ

6

Ненавижу прерывать этот разговор, который у вас с собой. :-)

Но ответ заключается в том, что VS2010 еще не полностью реализует спецификацию C++ 11 (для чего потребуется немного времени). Test должен иметь конструктор перемещения noexcept по умолчанию, который вызывает конструктор перемещения unique_ptr. VS2010 не реализует этот неявный конструктор перемещения Test. Если это так, ваш полный пример будет компилироваться и выполняться, как ожидалось. vector будет использовать noexcept move constructors для перемещения вещей, когда это необходимо.

+0

Я ценю прерывание! :-) Я никогда бы не догадался, что проблема в том, что V10 (и теперь VC11) не реализует 'noexcept'. http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx – dsmtoday

0

(другой случай, когда выписывание и проводкой вопрос привел к ответу)

Ответ, конечно, является то, что unique_ptr<> не имеет копии семантики. Тем не менее, я смог использовать вышеуказанное соглашение до тех пор, пока мне не потребовалось позвонить resize(). Я не думал о том, что resize() потенциально должен переместить блок и элементы внутри другого блока памяти. Вот когда происходит копирование. Несмотря на то, что он является исключительно временным, он по-прежнему нарушает уникальность unique_ptr<> во время копирования.

Что еще меня смутило, так как unique_ptr<> не имеет семантики копии, vector<unique_ptr<>> тоже не должен работать. Но ответ должен заключаться в том, что для этого случая была написана специализированная специализация.

Возможно, я мог бы написать специализацию шаблона для vector<Test>, чтобы избежать ленивого копирования векторного класса по умолчанию и, таким образом, избежать описанных выше ошибок компилятора. Но мое использование этой структуры не требует производительности, поэтому вместо ее использования shared_ptr<> с ее семантикой копирования выполняет все, что мне нужно.