何时从内存中删除匿名对象以及建议何时使用它们
When does the anonymous objects get deleted from memory and when it is recommended to use them?
我是 c++ 的新手,我试图了解构造函数和析构函数以及一些关于内存管理的知识。在下面的代码中,除了
1.MyClass((.disp((; 2.新的我的班级; 3.新我的班级(300(;
1(我想知道将所有这三个对象称为匿名对象是否正确。2(对于MyClass((,我知道这会创建一个对象并立即销毁它,因此没有内存问题。但是对于新的 MyClass((,析构函数永远不会被调用。我也明白,因为这是在堆上,我将不得不显式删除对象。但是在这种情况下我该怎么做呢?
如果不可能,程序执行后该内存何时可用?3(我还想知道这种类型的对象创建(新MyClass(有用的场景。
#include<iostream>
#include<conio.h>
using namespace std;
class MyClass
{
private:
int num;
public:
MyClass()
{
cout<<"no-arg constructor"<<endl;
}
MyClass(int num)
{
this->num=num;
cout<<"one param constructor"<<endl;
}
~MyClass()
{
cout<<"inside destructort"<<num<<endl;
}
void disp()
{
cout<<num<<endl;
}
};
int main()
{
MyClass m1;
MyClass m2(200);
MyClass *m3=new MyClass;
MyClass *m4=new MyClass(400);
MyClass().disp();
new MyClass;
new MyClass(300);
delete m4;
delete m3;
return 0;
}
"匿名对象"不是一个标准术语,它是一个描述性术语。我会把它解释为一个没有名字的对象。具有名称的对象称为变量或数据成员。
-
在表达式
MyClass().disp()
中,您将在类MyClass
的临时对象上调用成员函数disp
。临时对象的生存期延长 [1] 到完整表达式的末尾。如果我没记错的话,这在C++标准中被称为全表达式。 -
new
表达式new MyClass
为新的MyClass
对象分配内存,并在该内存块中创建新的MyClass
对象。表达式生成指向新对象的指针。可以将该指针存储在变量中,并在后面的delete
表达式中使用它来销毁对象并释放其内存。 -
表达式
new MyClass(300)
是相同的,只是为MyClass
构造函数提供了一个参数。new
-expression 语法还提供了用于指定分配操作参数的表示法。但这更高级,很少需要,无论如何,作为初学者,您应该优先不要使用原始new
或delete
,而是使用标准库容器和字符串。
如果new
没有相应的delete
,则对象一直存在到程序执行结束。如果这是一台带有操作系统的计算机,则操作系统将回收内存。但是,OS 对C++对象一无所知,因此不会调用对象析构函数,因此不会执行析构函数中指定的清理。
你问new
哪里有用。通常,当对象的所需生存期不适合范围(局部自动变量的嵌套生存期(和/或需要动态大小对象时。使用 new
来控制生命周期对于高效可移动的对象(如 C++11 及更高版本(来说问题不大,对于动态大小,优先使用容器(如 std::vector
(和字符串(如 std::string
(。
[1] 更一般地说,临时对象可以直接绑定到局部引用,在这种情况下,其生存期延长至引用的生存期,即在封闭块之外。
通常,您会在堆栈上分配对象,因为它更快,并且不需要删除它。
但是,如果要返回指针,则必须在堆上分配它。例如
int *foo(int n)
{
int *pn = new int(n);
return pn;
}
现在,调用方负责释放内存。
int main()
{
try {
int *ptr = foo(6);
// use ptr
delete ptr;
} catch (std::bad_alloc &ba) {
std::cerr << ba.what() << 'n';
}
}
你的错误是不存储new
的返回值。如果不存储返回值,您将如何使用内存?你将如何释放它?这就像付了一张电影票,然后把它扔掉了。
您的程序还有其他错误。 main
必须返回int
,而不是void
。使用标准getchar
函数而不是 getch
也是一个更好的主意。
我还在代码中添加了异常处理,因为new
在无法分配时会引发异常。将整个main
函数代码包装在try
块中是C++代码中的常见习惯用法。
除了干杯和hth。 - 阿尔夫的回答,但是我会添加这个...
如果您真的想要并且必须在堆上创建一个类 Bar
的临时对象,只需使用 std::make_shared (C++11( 或 std::make_unique (C++14(....
例:
std::make_unique<Bar>()->foo()
std::make_shared<Bar>()->foo()
上面创建了Bar
并调用它的方法foo()
。 Bar
的析构函数在 foo()
完成后被调用,并且总是删除其关联的内存。
可以像旧C++那样编写一个简单的类和函数,但由于可变参数模板和完美的转发,它不能是通用的
免费建议:避免任何需要上述情况的情况...即使是下面的代码(据说比堆更有效(在代码审查中通常也会皱眉
Bar().foo()
3(新对象仍然可以通过this
引用,所以你可以做(1)
或(2)
,或者只是将指针作为参数传递或从函数(3)
返回。
#include <vector>
#include <iostream>
class MyClass;
std::vector<MyClass*> vec;
class MyClass {
public:
// (1)
MyClass() { std::cout << 'c'; vec.push_back(this); }
~MyClass() { std::cout << 'd'; }
// OR (2)
MyClass* doSmth() { /* do some work; */ return this; }
void destroy() { delete this; }
// OR (3)
static void doAndDelete(MyClass* p)
{
// do smth
delete p;
}
static MyClass* creator() { return new MyClass; }
};
int main() {
// (1)
new MyClass;
for (auto x : vec)
delete x;
vec.clear();
// OR (2)
(new MyClass())->doSmth()->destroy();
// OR (3)
MyClass::doAndDelete(new MyClass);
MyClass* p = MyClass::creator();
delete p;
}
有时可能有用
- 是否可以将不可复制的成员用作使对象不可复制的替代方法?
- C++定义构造函数使对象成为非 POD
- 何时使函数成为类成员函数C++?
- C++ GLUT 使对象在视口外消失
- 如何使对象通过RVALUE参考通过而没有复制
- OpenGL使对象坚持到相机
- 如何使对象可以访问上课的其余部分
- 为什么我不能使对象 m1
- 按类使对象的向量
- 不能重载 = 使对象 1 = 0;
- 使对象在 C++-SFML 中平滑移动
- 三维模型平移使对象变形
- 如何在Google V8 Javascript引擎中使对象不可变
- swig:使c++对象在perl中可打印
- 使用 QQmlContext::setContextObject 使 C++ 对象对 QML 可见
- 何时对对象使用 new,何时使用指针
- 使对象围绕全局轴Directx旋转
- 使对象跟随鼠标
- 根据C++中的输入参数使对象属于一个类
- 使对象的C++数组在Python中可迭代