Использование push_back(std::move()) в векторе unique_ptr

#c #c 17

Вопрос:

Здравствуйте, я изучал c и наткнулся на unique_ptr. Я хочу поместить целые числа в этот вектор. Я использовал вектор, потому что тоже хотел попрактиковаться в итераторах…

 auto integerArray = std::vector<std::unique_ptr<int[]>>(10);
std::cout << "Created:" << sizeof(integerArray)/sizeof(int) << std::endl;
for (int i = 0; i<10;i  ) {
    int num = i * 10;
    integerArray.push_back((std::vector<std::unique_ptr<int>>)std::move(num)); //compile error here
}

std::cout << "Output : ";
for (auto constamp; i : integerArray) {
    std::cout << i << std::endl;
}
 

В этом и заключается ошибка:

 error C2664: 'void std::vector<std::unique_ptr<int [],std::default_delete<int []>>,std::allocator<std::unique_ptr<int [],std::default_delete<int []>>>>::push_back(const _Ty amp;)': cannot convert argument 1 from 'std::vector<std::unique_ptr<int,std::default_delete<int>>,std::allocator<std::unique_ptr<int,std::default_delete<int>>>>' to 'const _Ty amp;'
        with
        [
            _Ty=std::unique_ptr<int [],std::default_delete<int []>>
        ]
note: Reason: cannot convert from 'std::vector<std::unique_ptr<int,std::default_delete<int>>,std::allocator<std::unique_ptr<int,std::default_delete<int>>>>' to 'const _Ty'
        with
        [
            _Ty=std::unique_ptr<int [],std::default_delete<int []>>
        ]
note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
vector(633): note: see declaration of 'std::vector<std::unique_ptr<int [],std::default_delete<int []>>,std::allocator<std::unique_ptr<int [],std::default_delete<int []>>>>::push_back'
 

и почему в первом выводе cout указано 4 вместо 10? Я ожидал 10, потому что я сделал векторный контейнер с 10 блоками, которые могут содержать целое число.

Комментарии:

1. sizeof(integerArray)/sizeof(int) — для вектора это бессмысленно. Воспользуйся .size()

2. integerArray-это не вектор int, это вектор unique_ptrs, указывающий на массивы int

3. хорошо, я сделаю это . Но почему это не имеет никакого значения в векторе? потому что это не последовательно складывается в памяти, как массивы?

4. @Nakta_Na std::vector хранит динамическое количество элементов, поэтому ему требуется объем памяти, который неизвестен во время компиляции. Но sizeof это должна быть константа времени компиляции, поэтому она не включает хранение элементов. Хранилище для элементов получено из бесплатного магазина, поэтому не включено в a sizeof(std::vector<T>) . Этот размер включает только счетчики или указатели, используемые для управления этой памятью.

5. std::вектор, будет управлять памятью для вас (как это круто!). . std::unique_ptr обозначает право собственности, он четко сообщит, кто должен будет выполнить соответствующее удаление. Вы создаете unique_ptr<T> с помощью std::make_unique, и если вы хотите, чтобы какой-то другой код выполнял удаление за вас, вы используете std::move (передача права собственности). Примечание. После перемещения вы больше не можете использовать указатель самостоятельно. (Тогда есть также shared_ptr, но это уже другая история). Резюме : в современном C вы вряд ли увидите новые/удаленные массивы или массивы в стиле «c» (за исключением внутреннего кода библиотеки). Поэтому попробуйте написать код без них

Ответ №1:

Вы неправильно понимаете, как std::vector это работает. Он уже управляет своим содержимым и std::unique_ptr в данном случае не подходит. Вы также объявляете указатели на то, чтобы int быть типом в том unique_ptr же.

Если все, что вам нужно, — это контейнер целых чисел, это все, что необходимо:

 auto integerVector = std::vector<int>(10); // filled with 10 default-init values, 0 for int
std::cout << "Created:" << integerVector.size() << std::endl;
for (int i = 0; i<10;i  ) {
    int num = i * 10;
    integerVector.push_back(num); // Adds it to the end, not just first "unfilled"
}

std::cout << "Output : ";
for (auto constamp; i : integerVector) {
    // Will print 20 times, as original 10 "0", and the
    // 10 you added to the end
    std::cout << i << std::endl;
}
 

Будьте очень осторожны с именами «массив» и «вектор», поскольку они не одно и то же в c . Они похожи, но совсем не идентичны.

Комментарии:

1. Я рад, что это полезно для вас. Пожалуйста, отметьте мой ответ как «принято», если это то, что, по вашему мнению, помогло вам ответить на ваш вопрос. И отметьте «вверх» в рейтинге рядом с ним, если вы чувствуете, что он этого заслуживает.

2. Сделал «принято», но мне нужно больше повторений, чтобы отметить «вверх». Я буду активен в этом сообществе, и когда у меня будет достаточно репутации, чтобы сделать это, я сделаю это первым в вашем ответе.

3. Вы правы. Я отредактирую свой ответ, чтобы он был точным на 100%. Спасибо @AlanBirtles

4. Я надеюсь, что это все. Спасибо, что указали на это @AlanBirtles. Другие могут рассердиться, но я ценю это. Я бы предпочел, чтобы это было правильно.