Saya memerlukan wadah C++ dengan persyaratan berikut:
- Wadah dapat menyimpan objek yang tidak dapat disalin DAN tidak dapat dipindahkan dalam memori berkelanjutan. Untuk
std::vector
objek harus dapat disalin atau dipindahkan. capacity
kontainer diketahui selama konstruksi pada saat run-time, dan diperbaiki hingga kehancuran. Semua ruang memori yang dibutuhkan dialokasikan selama konstruksi. Untukboost::static_vector
kapasitasnya diketahui pada waktu kompilasi.- Ukuran penampung dapat bertambah seiring waktu ketika
emplace_back
lebih banyak elemen dalam penampung, tetapi tidak boleh melebihicapacity
. - Karena objek tidak dapat disalin atau dipindahkan, realokasi tidak diperbolehkan.
Tampaknya baik STL maupun BOOST tidak memiliki tipe container yang saya perlukan. Saya juga telah mencari di sisi ini secara ekstensif tetapi tidak menemukan jawaban. Jadi saya telah menerapkannya.
#include <memory>
template<class T>
class FixedCapacityVector {
private:
using StorageType = std::aligned_storage_t<sizeof(T), alignof(T)>;
static_assert(sizeof(StorageType) == sizeof(T));
public:
FixedCapacityVector(FixedCapacityVector const&) = delete;
FixedCapacityVector& operator=(FixedCapacityVector const&) = delete;
FixedCapacityVector(size_t capacity = 0):
capacity_{ capacity },
data_{ std::make_unique<StorageType[]>(capacity) }
{ }
~FixedCapacityVector()
{
for (size_t i = 0; i < size_; i++)
reinterpret_cast<T&>(data_[i]).~T();
}
template<class... Args>
T& emplace_back(Args&&... args)
{
if (size_ == capacity_)
throw std::bad_alloc{};
new (&data_[size_]) T{ std::forward<Args>(args)... };
return reinterpret_cast<T&>(data_[size_++]);
}
T& operator[](size_t i)
{ return reinterpret_cast<T&>(data_[i]); }
T const& operator[](size_t i) const
{ return reinterpret_cast<T const&>(data_[i]); }
size_t size() const { return size_; }
size_t capacity() const { return capacity_; }
T* data() { return reinterpret_cast<T*>(data_.get()); }
T const* data() const { return reinterpret_cast<T const*>(data_.get()); }
private:
size_t const capacity_;
std::unique_ptr<StorageType[]> const data_;
size_t size_{ 0 };
};
Pertanyaan saya adalah:
- Mengapa saya melakukan ini dengan tangan? Saya tidak dapat menemukan wadah standar. Atau mungkin saya tidak melihat tempat yang tepat? Atau karena apa yang saya coba lakukan tidak konvensional?
- Apakah wadah tulisan tangan diterapkan dengan benar? Bagaimana dengan keamanan pengecualian, keamanan memori, dll.?
std::shared_ptr
, dan kemudianstd::shared_ptr
disimpan distd::vector
? - person Eljay   schedule 26.12.2018std::vector<std::unique_ptr>
). Mungkin sebaiknya saya tidak menyebutkan jenis container yang umum dibutuhkan seperti itu. - person Tony Xiang   schedule 26.12.2018std::vector
saja yang diubah ukurannya sesuai kebutuhan maksimum, dan melacak berapa banyak elemen yang sebenarnya digunakan? Jika vektor tersebut adalah anggota privat kelas Anda, Anda dapat memastikan vektor tersebut tidak pernah diubah ukurannya setelah inisialisasi, apa pun yang dilakukan pengguna kelas Anda. Lagi pula, bahkan jika pengguna meminta kelas Anda untukemplace_back()
sesuatu, kelas Anda (atau implementasi fungsi anggotanya) tidak perlu mengubahnya menjadi panggilanemplace_back()
vektor. - person Peter   schedule 26.12.2018std::vector<T>
tidak akan dikompilasi jikaT
tidak dapat disalin dan dipindahkan. - person Tony Xiang   schedule 26.12.2018p->~T()
valid jikap
adalah penunjuk keT
yang tidak dirusak. Namun, Anda harus berhati-hati dalam memilih operasi pada vektor, karena beberapa fungsi anggotastd::vector
memiliki persyaratan yang lebih ketat (misalnya,emplace()
vektor [dari memori] mengharuskan elemennya adalah Move Assignable, Move Insertable, dan Emplace Constructible - sebagai pembeda dari salinan dapat dialihkan dan dapat disalin). - person Peter   schedule 26.12.2018std::vector<T>
untukT
yang tidak dapat disalin-tidak dapat dipindahkan. Seperti yang Anda katakan, instantiasi itu sendiri dapat dikompilasi. Namun, metode ini tidak dapat digunakan untuk menambahkan elemen ke vektor. Saya pikiremplace_back
dapat digunakan karena tidak memerlukan tindakan salin atau pindahkan jika tidak diperlukan realokasi. Namun kompiler masih mengeluhkan konstruktor salinan yang dihapus. Apakah Anda tahu cara menambahkan elemen ke vektor dalam kasus ini? - person Tony Xiang   schedule 26.12.2018