繁体   English   中英

C ++中的内存管理

[英]Memory Management in C++

我正在尝试测试如何以及在何处定位和销毁数据。 对于下面的示例代码:

  1. 创建一个新点并使用NewCartesian方法返回。 我知道它应该存储在堆中。 将其推回向量中时,是否将点内容的内存复制到新的Point结构中? 还是将此指针存储为参考?

  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; } 

谢谢您的帮助,

干杯,

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

首先,请阅读以下说明,为什么最好谈论自动动态对象生存期而不是堆栈/堆。

其次,该对象既不动态分配也不在堆上。 您可以知道,因为动态分配使用new expression或malloccalloc或可能的mmap类的库函数。 如果您没有任何一个(而且几乎从来没有),那么它就不是动态的。

您要按值返回某事物,因此该事物的生命周期绝对是自动的。

创建点时,什么时候销毁它?

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

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

我应该使用Point&p还是Point p来返回Point :: NewCartesian?

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

最后,这段代码

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

很奇怪-很难通过读取代码来确定p所指的Point的生存期。 NewCartesian可以将某个具有动态生存期的静态/全局/其他对象返回给其引用, 或者 (实际上)将引用绑定到匿名临时对象。 用这种方式代替它编写没有任何好处

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

或仅将临时笔直传递给push_back如您的注释代码中所示。


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

1a。 不,它在堆栈上,但请阅读Useless答案 ,为什么术语堆栈不是最佳选择。

1b。 当您调用push_back时,它将被复制。

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

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

3b。 您应该使用Point p ,而不是Point& p ,因为现在您可以悬空引用一个不再存在的对象(请参阅2.)。

正如史蒂文· vectorPoint.push_back( Point::NewCartesian(5, 10) ); Steven W. Klassen)在评论中指出的那样,最好的选择是注释掉的代码: vectorPoint.push_back( Point::NewCartesian(5, 10) ); NewCartesian的调用直接传递到push_back而无需创建单独的本地副本,从而使编译器可以对其进行优化,以便在push_back精确地构造内存,并避免任何中间内存分配或副本。 (或更确切地说,它允许它使用move运算符。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM