std::unique_ptr
memiliki dukungan untuk array, misalnya:
std::unique_ptr<int[]> p(new int[10]);
tapi apakah itu diperlukan? mungkin hal ini lebih nyaman untuk menggunakan std::vektor
atau std::array
.
Apakah anda menemukan gunakan untuk membangun?
Beberapa orang tidak memiliki kemewahan menggunakan std::vektor
, bahkan dengan penyalur. Beberapa orang membutuhkan dinamis berukuran array, jadi std::array
keluar. Dan beberapa orang mendapatkan mereka array dari kode lain yang dikenal untuk mengembalikan array; dan bahwa kode isn't akan ditulis ulang untuk kembali vektor
atau sesuatu.
Dengan memungkinkan unique_ptr<T[]>
, anda layanan kebutuhan tersebut.
Singkatnya, anda menggunakan unique_ptr<T[]>
ketika anda perlu untuk. Ketika alternatif yang cukup aren't akan bekerja untuk anda. It's a tool of last resort.
Ada pengorbanan, dan anda memilih solusi yang sesuai dengan apa yang anda inginkan. Dari atas kepala saya:
Ukuran awal
vektor
dan unique_ptr<T[]>
memungkinkan ukuran akan ditentukan pada saat run-timearray
hanya memungkinkan ukuran akan ditentukan pada waktu kompilasiUkuran
array
dan unique_ptr<T[]>
tidak memungkinkan resizevektor
tidakPenyimpanan
vektor
dan unique_ptr<T[]>
menyimpan data di luar objek (biasanya pada tumpukan)array
menyimpan data secara langsung pada objekMenyalin
array
dan vektor
memungkinkan menyalinunique_ptr<T[]>
tidak memungkinkan menyalinSwap/bergerak
vektor
dan unique_ptr<T[]>
memiliki O(1) waktu swap
dan memindahkan operasiarray
memiliki O(n) time swap
dan memindahkan operasi, di mana n adalah jumlah elemen dalam arrayPointer/referensi/iterator pembatalan
array
memastikan petunjuk, referensi dan iterator tidak akan valid sementara objek hidup, bahkan pada swap()
unique_ptr<T[]>
tidak memiliki iterator; pointer dan referensi hanya berlaku akibat swap()
sementara objek hidup. (Setelah menukar, arahkan pointer ke array yang anda swap dengan anda, sehingga mereka're masih "yang masih berlaku" dalam arti itu.)vektor
dapat membatalkan petunjuk, referensi dan iterator pada setiap realokasi (dan menyediakan beberapa jaminan bahwa realokasi hanya dapat terjadi pada operasi tertentu).Kompatibilitas dengan konsep dan algoritma
array
dan vektor
keduanya Wadahunique_ptr<T[]>
bukan WadahSaya harus mengakui, ini terlihat seperti sebuah kesempatan untuk beberapa refactoring dengan kebijakan berbasis desain.
Salah satu alasan anda mungkin menggunakan unique_ptr
adalah jika anda don't ingin membayar runtime biaya nilai inisialisasi array.
std::vector<char> vec(1000000); // allocates AND value-initializes 1000000 chars
std::unique_ptr<char[]> p(new char[1000000]); // allocates storage for 1000000 chars
The std::vektor
konstruktor dan std::vektor::resize()
akan nilai-menginisialisasi T
tapi baru
tidak akan melakukan itu jika T
adalah sebuah POD.
Perhatikan bahwa vektor::cadangan
bukan merupakan alternatif berikut: https://stackoverflow.com/questions/8228072/is-accessing-the-raw-pointer-after-stdvectorreserve-safe
It's alasan yang sama C programmer mungkin memilih malloc
atas calloc
.
Sebuah std::vektor
dapat disalin, sementara unique_ptr<int[]>
memungkinkan mengekspresikan unik kepemilikan dari array. std::array
, di sisi lain, membutuhkan ukuran yang akan ditentukan pada saat kompilasi, yang mungkin mustahil dalam beberapa situasi.
Scott Meyers mengatakan dalam Modern yang Efektif C++
keberadaan
std::unique_ptr
untuk array harus hanya intelektual yang menarik untuk anda, karenastd::array
,std::vektor
,std::string
yang hampir selalu baik struktur data pilihan dari baku array. Tentang satu-satunya situasi yang saya dapat membayangkan ketikastd::unique_ptr<T[]>
akan membuat rasa akan sama ketika anda're menggunakan C-seperti API yang kembali mentah pointer ke tumpukan array bahwa anda menganggap kepemilikan.
Saya berpikir bahwa Charles Salvia's jawaban yang lebih relevan meskipun: bahwa std::unique_ptr<T[]>
adalah satu-satunya cara untuk menginisialisasi array kosong yang ukurannya tidak diketahui pada waktu kompilasi. Apa yang akan Scott Meyers harus mengatakan tentang hal ini motivasi untuk menggunakan std::unique_ptr<T[]>
?
Bertentangan dengan std::vektor
dan std::array
, std::unique_ptr
dapat memiliki pointer NULL.
Hal ini sangat berguna ketika bekerja dengan C Api yang mengharapkan berupa array atau NULL:
void legacy_func(const int *array_or_null);
void some_func() {
std::unique_ptr<int[]> ptr;
if (some_condition) {
ptr.reset(new int[10]);
}
legacy_func(ptr.get());
}
Saya telah menggunakan unique_ptr<char[]>
untuk menerapkan preallocated renang memori yang digunakan pada mesin game. Idenya adalah untuk memberikan preallocated renang memori yang digunakan bukan dinamis alokasi untuk kembali tabrakan permintaan hasil dan hal-hal lain seperti fisika partikel tanpa harus mengalokasikan / free memori pada masing-masing frame. It's cukup nyaman untuk jenis skenario di mana anda perlu memori renang untuk mengalokasikan objek dengan kehidupan yang terbatas waktu (biasanya satu, 2 atau 3 frame) yang tidak memerlukan penghancuran logika (hanya memori deallocation).
Singkatnya:'s paling hemat memori.
A std::string
dilengkapi dengan pointer, panjang, dan "pendek-string-optimasi" buffer. Tapi situasi saya adalah saya perlu untuk menyimpan string yang hampir selalu kosong, dalam struktur yang aku punya ratusan ribu. Dalam C, saya hanya akan menggunakan char *
, dan itu akan menjadi null sebagian besar waktu. Yang bekerja untuk C++, terlalu, kecuali bahwa char *
tidak memiliki destructor, dan doesn't tahu untuk menghapus itu sendiri. Sebaliknya, std::unique_ptr<char[]>
akan menghapus dirinya sendiri ketika ia pergi keluar dari ruang lingkup. Kosong std::string
memakan 32 byte, tapi kosong std::unique_ptr<char[]>
membutuhkan 8 byte, yang, tepat ukuran pointer.
Kelemahan terbesar adalah, setiap kali saya ingin mengetahui panjang string, aku harus menelepon strlen
di atasnya.
Pola umum yang dapat ditemukan di [beberapa][GetPackageApplicationIds_MSDN] Windows Win32 API panggilan, di mana penggunaan std::unique_ptr<T[]>
dapat berguna, misalnya ketika anda don't tahu persis seberapa besar output buffer harus saat memanggil beberapa Win32 API (yang akan menulis beberapa data dalam buffer):
// Buffer dynamically allocated by the caller, and filled by some Win32 API function.
// (Allocation will be made inside the 'while' loop below.)
std::unique_ptr<BYTE[]> buffer;
// Buffer length, in bytes.
// Initialize with some initial length that you expect to succeed at the first API call.
UINT32 bufferLength = /* ... */;
LONG returnCode = ERROR_INSUFFICIENT_BUFFER;
while (returnCode == ERROR_INSUFFICIENT_BUFFER)
{
// Allocate buffer of specified length
buffer.reset( BYTE[bufferLength] );
//
// Or, in C++14, could use make_unique() instead, e.g.
//
// buffer = std::make_unique<BYTE[]>(bufferLength);
//
//
// Call some Win32 API.
//
// If the size of the buffer (stored in 'bufferLength') is not big enough,
// the API will return ERROR_INSUFFICIENT_BUFFER, and the required size
// in the [in, out] parameter 'bufferLength'.
// In that case, there will be another try in the next loop iteration
// (with the allocation of a bigger buffer).
//
// Else, we'll exit the while loop body, and there will be either a failure
// different from ERROR_INSUFFICIENT_BUFFER, or the call will be successful
// and the required information will be available in the buffer.
//
returnCode = ::SomeApiCall(inParam1, inParam2, inParam3,
&bufferLength, // size of output buffer
buffer.get(), // output buffer pointer
&outParam1, &outParam2);
}
if (Failed(returnCode))
{
// Handle failure, or throw exception, etc.
...
}
// All right!
// Do some processing with the returned information...
...
[GetPackageApplicationIds_MSDN]: http://msdn.microsoft.com/en-us/library/windows/desktop/dn270603(v=vs. 85).aspx
Saya menghadapi sebuah kasus di mana saya harus menggunakan std::unique_ptr<bool[]>
, yang berada di HDF5 perpustakaan (perpustakaan untuk efisien biner penyimpanan data, banyak digunakan dalam ilmu pengetahuan). Beberapa kompiler (Visual Studio 2015 di kasus saya) memberikan kompresi std::vektor<bool>
(dengan menggunakan 8 bools di setiap byte), yang merupakan bencana untuk sesuatu seperti HDF5, yang doesn't peduli tentang hal itu kompresi. Dengan std::vektor<bool>
, HDF5 akhirnya membaca sampah karena kompresi.
Tebak siapa yang ada di sana untuk menyelamatkan, dalam kasus di mana std::vektor
didn't bekerja, dan saya perlu untuk mengalokasikan array dinamis bersih? :-)
Salah satu alasan tambahan untuk memungkinkan dan menggunakan std::unique_ptr<T[]>
, yang belum't telah disebutkan dalam tanggapan sejauh ini: hal ini memungkinkan anda untuk maju mendeklarasikan array jenis elemen.
Hal ini berguna ketika anda ingin meminimalkan dirantai #include
pernyataan di header (untuk mengoptimalkan membangun kinerja.)
Untuk contoh -
myclass.h:
class ALargeAndComplicatedClassWithLotsOfDependencies;
class MyClass {
...
private:
std::unique_ptr<ALargeAndComplicatedClassWithLotsOfDependencies[]> m_InternalArray;
};
myclass.cpp:
#include "myclass.h"
#include "ALargeAndComplicatedClassWithLotsOfDependencies.h"
// MyClass implementation goes here
Dengan kode di atas struktur, siapa pun dapat #include "myclass.h"
dan menggunakan MyClass
, tanpa harus mencakup pelaksanaan internal dependensi yang diperlukan oleh MyClass::m_InternalArray
.
Jika m_InternalArray
malah dinyatakan sebagai std::array<ALargeAndComplicatedClassWithLotsofdependencies>
, atau std::vektor<...>
, masing - hasilnya akan mencoba penggunaan aplikasi yang tidak lengkap jenis, yang adalah compile-time error.
Untuk menjawab orang-orang yang berpikir anda "untuk" menggunakan vektor
bukan unique_ptr
saya punya kasus di CUDA pemrograman pada GPU ketika anda mengalokasikan memori di Perangkat, anda harus pergi untuk sebuah array pointer (dengan cudaMalloc
).
Kemudian, ketika mengambil data ini di Host, anda harus pergi lagi untuk pointer dan unique_ptr
baik-baik saja untuk menangani pointer dengan mudah.
Tambahan biaya konversi double*
untuk vektor<ganda>
adalah tidak perlu dan menyebabkan hilangnya perf.
new[]
std::vektor
, misalnya, untuk mencegah ceroboh programmer dari sengaja memperkenalkan salinanAda aturan umum bahwa C++ wadah untuk menjadi lebih disukai rolling-anda-sendiri dengan pointer. Ini adalah aturan umum; memiliki pengecualian. Ada's lebih, ini hanya contoh.
Mereka mungkin rightest jawabannya mungkin ketika anda hanya mendapatkan untuk menyodok tunggal melalui pointer yang ada API (berpikir jendela pesan atau threading yang berhubungan dengan parameter callback) yang memiliki beberapa ukuran seumur hidup setelah menjadi "menangkap" di sisi lain menetas, tapi yang tidak terkait untuk pemanggilan kode:
unique_ptr<byte[]> data = get_some_data();
threadpool->post_work([](void* param) { do_a_thing(unique_ptr<byte[]>((byte*)param)); },
data.release());
Kita semua ingin hal-hal yang bagus untuk kita. C++ adalah untuk lain kali.
unique_ptr<char[]> dapat digunakan di mana anda ingin kinerja C dan kenyamanan dari C++. Pertimbangkan yang anda butuhkan untuk beroperasi pada jutaan (ok, miliaran jika anda don't percaya belum) dari string. Menyimpan masing-masing dari mereka di tempat terpisah
stringatau
vektor
Namun, anda dapat mengalokasikan satu buffer untuk menyimpan banyak string. Anda tidak't seperti char* buffer = (char*)malloc(total_size);
untuk alasan yang jelas (jika tidak jelas, cari "mengapa menggunakan smart ptrs"). Anda akan lebih suka unique_ptr<char[]> buffer(new char[total_size]);
Dengan analogi, kinerja yang sama&kenyamanan pertimbangan berlaku untuk non-char
data (mempertimbangkan jutaan vektor/matriks/benda).