Dinamik ayırma yalnızca nesnenin ömrü, oluşturulduğu kapsamdan farklı olması gerektiğinde gereklidir (Bu, kapsamı küçültmek için de geçerlidir) ve değere göre depolamanın belirli bir nedeniniz varsa iş.
Örneğin:
std::vector<int> *createVector(); // Bad
std::vector<int> createVector(); // Good
auto v = new std::vector<int>(); // Bad
auto result = calculate(/*optional output = */ v);
auto v = std::vector<int>(); // Good
auto result = calculate(/*optional output = */ &v);
C ++ 11'den itibaren, std::unique_ptr
ayrılan belleğin sahipliğini içeren ayrılan bellekle uğraşmak zorundayız . std::shared_ptr
sahipliğinizi paylaşmanız gerektiğinde yaratıldı. (buna iyi bir programda beklediğinizden daha az ihtiyacınız olacaktır)
Bir örnek oluşturmak gerçekten çok kolay:
auto instance = std::make_unique<Class>(/*args*/); // C++14
auto instance = std::make_unique<Class>(new Class(/*args*/)); // C++11
auto instance = std::make_unique<Class[]>(42); // C++14
auto instance = std::make_unique<Class[]>(new Class[](42)); // C++11
C ++ 17 std::optional
, bellek ayırmalarını gerektirmenizi önleyen ekler
auto optInstance = std::optional<Class>{};
if (condition)
optInstance = Class{};
'Örnek' kapsam dışına çıkar çıkmaz bellek temizlenir. Sahipliği aktarmak da kolaydır:
auto vector = std::vector<std::unique_ptr<Interface>>{};
auto instance = std::make_unique<Class>();
vector.push_back(std::move(instance)); // std::move -> transfer (most of the time)
Peki hala ne zaman ihtiyacın var new
? C ++ 11'den neredeyse hiç. Çoğunluğu, std::make_unique
ham işaretçiler aracılığıyla sahipliğini aktaran bir API'ya ulaştığınız bir noktaya ulaşıncaya kadar kullanırsınız .
auto instance = std::make_unique<Class>();
legacyFunction(instance.release()); // Ownership being transferred
auto instance = std::unique_ptr<Class>{legacyFunction()}; // Ownership being captured in unique_ptr
C ++ 98 / 03'te manuel bellek yönetimi yapmanız gerekir. Bu durumda, standardın daha yeni bir sürümüne yükseltmeyi deneyin. Sıkıştıysanız:
auto instance = new Class(); // Allocate memory
delete instance; // Deallocate
auto instances = new Class[42](); // Allocate memory
delete[] instances; // Deallocate
Bellek sızıntısı olmaması için sahipliği doğru takip ettiğinizden emin olun! Hareket semantiği de henüz çalışmıyor.
Peki, ne zaman C ++ 'da malloc'a ihtiyacımız var? Tek geçerli neden bellek ayırmak ve daha sonra yeni yerleştirme yoluyla başlatmak olacaktır.
auto instanceBlob = std::malloc(sizeof(Class)); // Allocate memory
auto instance = new(instanceBlob)Class{}; // Initialize via constructor
instance.~Class(); // Destroy via destructor
std::free(instanceBlob); // Deallocate the memory
Yukarıdakiler geçerli olsa da, bu yeni bir operatör üzerinden de yapılabilir. std::vector
bunun için iyi bir örnek.
Son olarak, hala odasında fil var: C
. Belleğin C ++ kodunda ayrıldığı ve C kodunda (veya başka bir şekilde) serbest bırakıldığı bir C kitaplığıyla çalışmak zorundaysanız, malloc / free kullanmak zorunda kalırsınız.
Bu durumda sanal işlevleri, üye işlevlerini, sınıfları unutun ... Yalnızca içinde POD bulunan yapılara izin verilir.
Kuralların bazı istisnaları:
- Malloc'un uygun olduğu gelişmiş veri yapılarına sahip standart bir kütüphane yazıyorsunuz
- Büyük miktarda bellek ayırmanız gerekiyor (10 GB'lik bir dosyanın bellek kopyasında mı?)
- Belirli yapıları kullanmanızı engelleyen takımlarınız var
- Eksik bir türü saklamanız gerekiyor