首页 > 解决方案 > C++ 中的内存管理

问题描述

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

  1. 使用 NewCartesian 方法创建并返回一个新点。我知道它应该存储在堆中。当它被推回向量中时,点内容的内存是否被复制到一个新的点结构中?还是将其存储为 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-memory

解决方案


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

首先,请阅读这个解释为什么最好谈论自动动态对象生命周期,而不是堆栈/堆。

其次,该对象既不是动态分配的,也不是在堆上的。您可以判断,因为动态分配使用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很奇怪。它具有公共数据成员,但有一个私有构造函数,以及一个仅调用构造函数的公共静态方法。您可以完全省略构造函数和静态方法而只使用聚合初始化,或者省略静态方法并使构造函数公开。


推荐阅读