[英]C++: What happens to a dynamically allocated object created as an argument in a constructor call?
[英]What Happens To Dynamically Allocated Variables Without Handles ? (C++)
像這樣實例化沒有句柄的類會導致 C++ 中的 memory 泄漏嗎?
new SomeClass();
在方法中傳遞它們怎么樣?
SomeMethod(new SomeClass())
在方法的定義超出 scope 之后,它們會被釋放嗎?
這聽起來像是一個愚蠢的問題,但據我所知,如果他們不被釋放,他們哪兒也去不了。
是的,你是對的。 默認 C++,每次調用new
后都必須跟delete
,否則就是 leak。 但是,在某些邊緣情況下,可以在不使用delete
的情況下使用new
。
一種這樣的情況是placement new ,其中 memory 分配由您自己處理。 例子:
#include <cstdint>
#include <memory>
#include <iostream>
struct X {
int a;
int b;
};
int main(int argc, char** argv) {
char buffer[256];
X* x1 = new (&buffer[0]) X{1,2};
X* x2 = new (&buffer[8]) X{3,4};
std::cout << "x1: " << x1->a << " " << x1->b << std::endl;
std::cout << "x2: " << x2->a << " " << x2->b << std::endl;
// no leaks since the memory is released when `buffer` is
// deallocated. However it is good practice to call the
// destructor directly
x1->~X();
x2->~X();
}
產生:
Program stdout
x1: 1 2
x2: 3 4
Godbolt: https://godbolt.org/z/sEPWadcKh
另一種情況是當 class覆蓋 operator new時,如本例所示:
#include <cstdint>
#include <memory>
#include <iostream>
static char buffer[32768];
static char* ptr = &buffer[0];
struct X {
int a;
int b;
void* operator new(size_t size) {
void* p = ptr;
ptr += size;
return p;
}
void operator delete(void*) {
// no need to do anything
}
};
int main(int argc, char** argv) {
X* x1 = new X{1,2};
X* x2 = new X{3,4};
std::cout << "x1: " << x1->a << " " << x1->b << std::endl;
std::cout << "xs: " << x2->a << " " << x2->b << std::endl;
// no leaks since the memory is released when `buffer` is
// deallocated. However it is good practice to call the
// destructor directly
x1->~X();
x2->~X();
}
產生:
Program stdout
x1: 1 2
x2: 3 4
Godbolt: https://godbolt.org/z/jc4r9qbxh
另一種情況是當您將new
與智能指針一起使用時,如下例所示
#include <cstdint>
#include <memory>
#include <iostream>
#include <boost/intrusive_ptr.hpp>
struct X {
X(int a_, int b_ ) : a(a_), b(b_){
std::cout << "Constructor " << this << std::endl;
}
~X() {
std::cout << "Destructor " << this << std::endl;
}
int a;
int b;
int count = 0;
};
void intrusive_ptr_add_ref(X* x)
{
++x->count;
}
void intrusive_ptr_release(X* x)
{
if (--x->count == 0)
delete x;
}
int main(int argc, char** argv) {
boost::intrusive_ptr<X> x1 = new X{1,2};
boost::intrusive_ptr<X> x2 = new X{3,4};
std::cout << "x1: " << x1->a << " " << x1->b << std::endl;
std::cout << "x2: " << x2->a << " " << x2->b << std::endl;
}
產生:
Constructor 0xb4b2b0
Constructor 0xb4c2e0
x1: 1 2
x2: 3 4
Destructor 0xb4c2e0
Destructor 0xb4b2b0
Godbolt: https://godbolt.org/z/b7MTfazT9
因此,雖然delete
是代表您調用的,但作為用戶的您不必自己調用delete
。
另一個用例是為管理對象生命周期的框架創建對象,如Qt 。
所以答案確實是肯定的,總是在new
之后調用delete
,但在行業中有很多情況並不是真的有必要。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.