代码之家  ›  专栏  ›  技术社区  ›  MeCe

C++中的内存管理

  •  0
  • MeCe  · 技术社区  · 6 年前

    我正在测试数据的位置和位置。对于下面的示例代码:

    1. 创建一个新的点,并用newcartesian方法返回。我知道应该把它堆起来。当它被推回到向量中时,点内容的内存是否被复制到一个新的点结构中?或者它存储为引用这个指针?

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

    谢谢你的帮助,

    干杯,

    2 回复  |  直到 6 年前
        1
  •  3
  •   Max Vollmer    6 年前

    不,在书堆上,但是读一下 answer 通过 Useless 为什么术语 堆栈 不是最好的选择。

    1b.你打电话的时候会收到副本 push_back .

    2。它在创建后立即被销毁,因为它只存在于 NewCartesian 在正在评估的返回期间调用和。

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

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

    正如所指出的 Steven W. Klassen 在注释中,您最好的选择是注释掉的代码: vectorPoint.push_back( Point::NewCartesian(5, 10) ); . 将呼叫传递给 新笛卡尔 直接进入 推挽 在不进行单独的本地复制的情况下,允许编译器对其进行优化,以便在 推挽 需要它并避免任何中间内存分配或复制。(或者更严格地说,它允许使用移动操作符。)

        2
  •  4
  •   Useless    6 年前

    …我知道应该把它堆起来。

    首先,请 read this 解释为什么最好谈谈 自动的 动态 对象生存期,而不是堆栈/堆。

    其次,该对象既不是动态分配的,也不是堆上的。因为动态分配使用 new -表达式或库函数 malloc , calloc 或者可能 mmap . 如果你没有这些(而且你几乎永远都不应该),它就不是动态的。

    你是按价值返回某物,所以这东西的生命周期绝对是自动的。

    何时创建点,何时销毁点?

    如果编写完整的复制/移动构造函数和赋值运算符集,再加上一个析构函数,则只需在调试器中设置断点,然后 看见 在那里被调用。或者,让他们全部打印 this 指针和输入参数(即从中移动或复制的源对象)。

    然而,由于我们知道对象是自动的,所以当它超出范围时,答案是容易的。

    我应该使用point&p还是point p返回point::newcartesian?

    当然是第二个:第一个返回对对象的引用,对象的自动生存期在 NewCartesian 函数,这意味着调用方获取引用时所引用的对象已经死了。

    最后,这个代码

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

    很奇怪-很难确定 Point p 通过阅读代码。它可以是具有动态生存期的静态/全局/其他对象, 新笛卡尔 返回引用, (实际上是这样)您可以将引用绑定到匿名临时对象。这样写没有什么好处,而不是

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

    或者直接通过临时通道 push_back 就像你的注释代码一样。


    作为旁白,设计 很奇怪。它有公共数据成员,但有一个私有的构造函数,以及一个只调用构造函数的公共静态方法。可以完全省略构造函数和静态方法,只使用聚合初始化,也可以省略静态方法并将构造函数设为公共的。