haha bez jaj, tworzenie unikalnego wskaźnika tylko po to, aby od razu oddać posiadaną wartość :) - WTF
Możesz sobie stworzyć sprytny wskaźnik na zapas, a zmienić mu unikalną wartość później.
std::unique_ptr<int> p;
// ...
p.reset(new int(5));
Zajrzałem do "Skuteczny nowoczesny C++" Meyersa i jak się okazuje są (oczywiście) jakieś śmieszne subtelności w związku z przekazywaniem doskonałym. Przykład jest podany ze std::vector
, który ma zarówno konstruktor akceptujący std::initializer_list
(std::vector<int>{10, 1}
tworzy wektor dwóch elementów, {10, 1}
) jak i parę wartości (std::vector<int>(10, 1)
tworzy wektor 10 elementów o wartości 1). Załóżmy teraz, że mamy ten sprytny wskaźnik na taki wektor:
std::unique_ptr<std::vector<int>> v;
I teraz chcemy go zastąpić wektorem, który ma dwa elementy, {10, 20}
. Wywołanie
v = std::make_unique<std::vector<int>>(10, 20);
Tworzy wektor 10 elementów, bo wywołuje tamten konstruktor. Wywołanie
v = std::make_unique<std::vector<int>>({10, 20});
Wyburacza się. Można zrobić tak:
auto initList = { 10, 20 };
v = std::make_unique<std::vector<int>>(initList);
Ale to ma dwie linijki ;). Natomiast przy reset
wywołujemy konstruktor jawnie, więc można zrobić:
v.reset(new std::vector<int>{10, 20});
Pełen kod testowy:
#include <memory>
#include <vector>
#include <iostream>
int main () {
std::unique_ptr<std::vector<int>> v;
v = std::make_unique<std::vector<int>>(10, 20);
std::cout << v->size() << std::endl; // 10
// v = std::make_unique<std::vector<int>>({10, 20});
// błąd kompilacji
auto initList = { 10, 20 };
v = std::make_unique<std::vector<int>>(initList);
std::cout << v->size() << std::endl; // 2
v.reset(new std::vector<int>{10, 20});
std::cout << v->size() << std::endl; // 2
v.reset(new std::vector<int>(10, 20));
std::cout << v->size() << std::endl; // 10
}
Po szczegóły odsyłam do punktu 21 wyżej wymienionej książki. Którą to kiedyś trzeba by znowu przeczytać :(