关于构造函数和内存泄漏的问题
Question about constructors & memory leak
我正在测试构造函数和析构函数,我想看看我是否可以将对象传递给函数而不先声明它,就像这个例子:
#include<iostream>
#include<stdlib.h>
using namespace std;
class car
{
public:
string name;
int num;
public:
car(string a, int n)
{
cout << "Constructor called" << endl;
this->name = a;
this->num = n;
}
~car()
{
cout << "Deleted" << endl;
}
};
void display(car* p)
{
cout << "Name: " << p->name << endl;
cout << "Num: " << p->num << endl;
}
int main()
{
display(new car("HYUNDAI", 2012));
}
display
函数运行良好,完全符合我的预期,但我想知道:
- 如果我在
display
的输入中声明了 new
关键字,为什么我的用户定义的析构函数没有被调用,并且
new
会导致内存泄漏吗?
Would that new cause a memory leak?
是的,它导致了内存泄漏。无论你 new
ed 应该 delete
ed 之后 wards(手动内存管理)。
why didn't my user-defined destructor get called?
因为对象还没有delete
d,因此没有被破坏。
你应该做的
void display(car* p)
{
if (p) // check p is valid pointer
{
std::cout << "Name: " << p->name << std::endl;
std::cout << "Num: " << p->num << std::endl;
// ...after use
delete p;
}
}
除了手动内存管理,您还可以使用智能指针。
What is a smart pointer and when should I use one?
也就是说,对于所示的案例,您不需要指针(除非您想用指针练习)。一种选择是将其作为 const car&
传递,这也适用于临时对象。
void display(const car& p)
// ^^^^^^^^^^^^
{
std::cout << "Name: " << p.name << std::endl;
std::cout << "Num: " << p.num << std::endl;
}
你可以将 car
作为
display(car{ "HYUNDAI", 2012 });
参见:What are the differences between a pointer variable and a reference variable in C++?
是的,您的程序中存在内存泄漏,因为每当您使用 new
关键字分配一些内存时,您必须始终使用 delete
在以后不再需要时释放该内存。否则你会像在你的程序中那样发生内存泄漏。有两种方法可以解决您的问题:
解决方案 1:明确使用删除
int main()
{
car * ptr = new car("HYUNDAI", 2012);
display(ptr);
//use delete to free up memory
delete ptr; //this will call the destructor
}
方案二:使用智能指针
#include<iostream>
#include<stdlib.h>
#include <memory>
using namespace std;
class car
{
public:
string name;
int num;
public:
car(string a, int n)
{
cout << "Constructor called" << endl;
this->name = a;
this->num = n;
}
~car()
{
cout << "Deleted" << endl;
}
};
void display(std::shared_ptr<car> p)
{
cout << "Name: " << p->name << endl;
cout << "Num: " << p->num << endl;
}
int main()
{
std::shared_ptr<car> ptr = std::make_shared<car>("HYUNDAI", 2012);
display(ptr);
//there is no memory leak
//you don't need to use delete explicitly
}
使用智能指针(如 shared_ptr 或 unique_ptr)的优点是您不必显式释放内存。
使用 unique_ptr 解决方案 2 看起来像:
#include<iostream>
#include<stdlib.h>
#include <memory>
using namespace std;
class car
{
public:
string name;
int num;
public:
car(string a, int n)
{
cout << "Constructor called" << endl;
this->name = a;
this->num = n;
}
~car()
{
cout << "Deleted" << endl;
}
};
void display(const std::unique_ptr<car> &p)
{
cout << "Name: " << p->name << endl;
cout << "Num: " << p->num << endl;
}
int main()
{
unique_ptr<car> p1(new car("HYUNDAI", 2012));
display(p1);
//there is no memory leak
//you don't need to use delete explicitly
}
请注意,在您的情况下,您不需要传递指向 display
的指针。您可以改为直接传递对象,如下所示:
#include<iostream>
#include<stdlib.h>
using namespace std;
class car
{
public:
string name;
int num;
public:
car(string a, int n)
{
cout << "Constructor called" << endl;
this->name = a;
this->num = n;
}
~car()
{
cout << "Deleted" << endl;
}
};
//note pass by value(other way would be to use pass by reference like const car& p)
void display(car p)
{
cout << "Name: " << p.name << endl;
cout << "Num: " << p.num << endl;
}
int main()
{
display(car("HYUNDAI", 2012));
}
我正在测试构造函数和析构函数,我想看看我是否可以将对象传递给函数而不先声明它,就像这个例子:
#include<iostream>
#include<stdlib.h>
using namespace std;
class car
{
public:
string name;
int num;
public:
car(string a, int n)
{
cout << "Constructor called" << endl;
this->name = a;
this->num = n;
}
~car()
{
cout << "Deleted" << endl;
}
};
void display(car* p)
{
cout << "Name: " << p->name << endl;
cout << "Num: " << p->num << endl;
}
int main()
{
display(new car("HYUNDAI", 2012));
}
display
函数运行良好,完全符合我的预期,但我想知道:
- 如果我在
display
的输入中声明了new
关键字,为什么我的用户定义的析构函数没有被调用,并且 new
会导致内存泄漏吗?
Would that new cause a memory leak?
是的,它导致了内存泄漏。无论你 new
ed 应该 delete
ed 之后 wards(手动内存管理)。
why didn't my user-defined destructor get called?
因为对象还没有delete
d,因此没有被破坏。
你应该做的
void display(car* p)
{
if (p) // check p is valid pointer
{
std::cout << "Name: " << p->name << std::endl;
std::cout << "Num: " << p->num << std::endl;
// ...after use
delete p;
}
}
除了手动内存管理,您还可以使用智能指针。
What is a smart pointer and when should I use one?
也就是说,对于所示的案例,您不需要指针(除非您想用指针练习)。一种选择是将其作为 const car&
传递,这也适用于临时对象。
void display(const car& p)
// ^^^^^^^^^^^^
{
std::cout << "Name: " << p.name << std::endl;
std::cout << "Num: " << p.num << std::endl;
}
你可以将 car
作为
display(car{ "HYUNDAI", 2012 });
参见:What are the differences between a pointer variable and a reference variable in C++?
是的,您的程序中存在内存泄漏,因为每当您使用 new
关键字分配一些内存时,您必须始终使用 delete
在以后不再需要时释放该内存。否则你会像在你的程序中那样发生内存泄漏。有两种方法可以解决您的问题:
解决方案 1:明确使用删除
int main()
{
car * ptr = new car("HYUNDAI", 2012);
display(ptr);
//use delete to free up memory
delete ptr; //this will call the destructor
}
方案二:使用智能指针
#include<iostream>
#include<stdlib.h>
#include <memory>
using namespace std;
class car
{
public:
string name;
int num;
public:
car(string a, int n)
{
cout << "Constructor called" << endl;
this->name = a;
this->num = n;
}
~car()
{
cout << "Deleted" << endl;
}
};
void display(std::shared_ptr<car> p)
{
cout << "Name: " << p->name << endl;
cout << "Num: " << p->num << endl;
}
int main()
{
std::shared_ptr<car> ptr = std::make_shared<car>("HYUNDAI", 2012);
display(ptr);
//there is no memory leak
//you don't need to use delete explicitly
}
使用智能指针(如 shared_ptr 或 unique_ptr)的优点是您不必显式释放内存。
使用 unique_ptr 解决方案 2 看起来像:
#include<iostream>
#include<stdlib.h>
#include <memory>
using namespace std;
class car
{
public:
string name;
int num;
public:
car(string a, int n)
{
cout << "Constructor called" << endl;
this->name = a;
this->num = n;
}
~car()
{
cout << "Deleted" << endl;
}
};
void display(const std::unique_ptr<car> &p)
{
cout << "Name: " << p->name << endl;
cout << "Num: " << p->num << endl;
}
int main()
{
unique_ptr<car> p1(new car("HYUNDAI", 2012));
display(p1);
//there is no memory leak
//you don't need to use delete explicitly
}
请注意,在您的情况下,您不需要传递指向 display
的指针。您可以改为直接传递对象,如下所示:
#include<iostream>
#include<stdlib.h>
using namespace std;
class car
{
public:
string name;
int num;
public:
car(string a, int n)
{
cout << "Constructor called" << endl;
this->name = a;
this->num = n;
}
~car()
{
cout << "Deleted" << endl;
}
};
//note pass by value(other way would be to use pass by reference like const car& p)
void display(car p)
{
cout << "Name: " << p.name << endl;
cout << "Num: " << p.num << endl;
}
int main()
{
display(car("HYUNDAI", 2012));
}