Jeśli jesteś w pozycji, w której vector<int>
jest możliwe, prawdopodobnie chcesz to zrobić z wyjątkiem ekstremalnych i rzadkich okoliczności.I nawet wtedy niestandardowy typ zamiast unique_ptr<int[]>
może być najlepszą odpowiedzią.
Co jest, do cholery, dobre dla unique_ptr<int[]>
? :-)
unique_ptr<T[]>
naprawdę świeci w dwóch przypadkach:
1.
trzeba obsłużyć malloc/free zasób z jakiejś funkcji starszego i chcesz to zrobić w bezpieczny styl nowoczesny wyjątek:
void
foo()
{
std::unique_ptr<char[], void(*)(void*)> p(strdup("some text"), std::free);
for (unsigned i = 0; p[i]; ++i)
std::cout << p[i];
std::cout << '\n';
}
2.
masz potrzeby tymczasowo zabezpieczyć nową [] zasobu przed przeniesieniem go do innego właściciela:
class X
{
int* data_;
std::string name_;
static void validate(const std::string& nm);
public:
~X() {delete [] data_;}
X(int* data, const std::string& name_of_data)
: data_(nullptr),
name_()
{
std::unique_ptr<int[]> hold(data); // noexcept
name_ = name_of_data; // might throw
validate(name_); // might throw
data_ = hold.release(); // noexcept
}
};
W powyższym scenariuszu X
jest właścicielem wskaźnika przekazanego do niego, niezależnie od tego, czy konstruktor się powiedzie, czy nie. Ten konkretny przykład zakłada domyślny konstruktor noexcept
dla std::string
, który nie jest zalecany. Jednak:
- Ten punkt można uogólnić na okoliczności, które nie dotyczą
std::string
.
- Domyślny konstruktor, który rzuca, jest kulawy.
Dlaczego nie użyć std :: array? – Bart
@Bart Nie musi powiększać pamięci po przydzieleniu, co nie znaczy, że zna rozmiar w czasie kompilacji. – Praetorian
@Bart Zaktualizowałem pytanie, zakładając, że rozmiar bufora nie jest znany podczas kompilacji. – huitlarc