C ++中的内存管理

问题描述 投票:0回答:2

我正在尝试测试数据的定位和销毁方式和位置。对于以下示例代码:

  1. 使用NewCartesian方法创建并返回一个新点。我知道它应该存储在堆中。当它被推回到向量中时,点内容的内存是否被复制到新的Point结构中?或者它存储为this指针的引用?
  2. 当点被创建时,它什么时候被破坏?当我完成它时,我是否需要破坏这些点?或者,当他们不再使用时,他们会被摧毁吗?例如,如果main是另一个函数,那么该向量在完成时将没有用处。
  3. 根据上面的答案,何时使用对象的引用是好的?我应该使用Point&p或Point p来返回Point :: NewCartesian吗? #define _USE_MATH_DEFINES #include <iostream> #include <cmath> using namespace std; struct Point { private: Point(float x, float y) : x(x), y(y) {} public: float x, y; static Point NewCartesian(float x, float y) { return{ x, y }; } }; int main() { vector<Point> vectorPoint; for (int i = 0; i < 10000; i++) { Point& p = Point::NewCartesian(5, 10); vectorPoint.push_back( p ); // vectorPoint.push_back( Point::NewCartesian(5, 10) ); Point& p2 = Point::NewPolar(5, M_PI_4); } cout << "deneme" << endl; getchar(); return 0; }

谢谢您的帮助,

干杯,

c++ heap heap-memory
2个回答
3
投票

1A。不,它在堆栈上,但是通过answer读取Useless,为什么术语堆栈和堆不是最佳选择。

1B。当你调用push_back时它会被复制。

2。它在创建后立即被销毁,因为它只存在于NewCartesian调用的范围内并且在评估返回的持续时间内。

3A。只要有了有效的实例,并且想要将其传递给函数而不创建副本,就可以使用引用。具体来说,该函数应该有一个参考参数。

3B。你应该使用Point p,而不是Point& p,因为现在你得到一个不再存在的对象的悬空引用(见2.)

正如Steven W. Klassen在评论中指出的那样,您最好的选择是您注释掉的代码:vectorPoint.push_back( Point::NewCartesian(5, 10) );。将调用NewCartesian直接传递到push_back而不制作单独的本地副本,允许编译器对其进行优化,以便在push_back想要它的地方构建内存并避免任何中间内存分配或复制。 (或者从技术上讲,它允许它使用移动运算符。)


4
投票

...我知道它应该存储在堆中。

首先,请read this解释为什么讨论自动和动态对象生命周期更好,而不是堆栈/堆。

其次,该对象既不是动态分配的,也不是堆上的。你可以说,因为动态分配使用new表达式,或者像malloccalloc或者mmap这样的库函数。如果你没有任何这些(你几乎从不应该),那它就不是动态的。

你是按价值归还的,所以这个东西的生命周期绝对是自动的。

当点被创建时,它什么时候被破坏?

如果编写完整的复制/移动构造函数和赋值运算符以及析构函数,只需在调试器中设置断点并查看它们的调用位置即可。或者,让他们都打印他们的this指针和输入参数(即,移动或复制源对象)。

但是,由于我们知道对象是自动的,所以答案很简单 - 当它超出范围时。

我应该使用Point&p或Point p来返回Point :: NewCartesian吗?

绝对是第二个:第一个返回对NewCartesian函数范围内具有自动生命周期的对象的引用,这意味着在调用者获取引用时,被引用的被引用已经死亡。

最后,这段代码

Point& p = Point::NewCartesian(5, 10);

很奇怪 - 通过阅读代码很难确定Point提到的p的寿命。它可能是一些具有动态生命周期的静态/全局/其他对象,NewCartesian返回一个引用,或者(实际上就是这种情况)您可以绑定对匿名临时的引用。以这种方式编写它没有任何好处,而不是

Point p = Point::NewCartesian(5, 10);

或者只是将临时直接传递给push_back,如评论代码中所示。


顺便说一下,Point的设计很奇怪。它有公共数据成员,但是私有构造函数和只调用构造函数的公共静态方法。您可以完全省略构造函数和静态方法,只使用聚合初始化,或省略静态方法并使构造函数公开。

© www.soinside.com 2019 - 2024. All rights reserved.