zoukankan      html  css  js  c++  java
  • 类的再理解

     

    参考资料:

    http://zhidao.baidu.com/link?url=Fjt8F2-hATIAzY3lvj8aMUNuKoHhkaH8K0ixvJCHMQdwmob5NRDaYAVGBBXo4nONHgLeBiLUBpIq-T0i8axsmK8Pjz6Ozz7Nennr-b3HBGi c++自定义类型中有个vector容器,容器里面是一些指针,如何写这个类的复制构造函数和重载=符?

     

    最近遇到一个很奇怪的问题:

    莫名其妙的有内存泄漏:而且下图中的109.2Mb 会一直增加,且是运行一段时间后再增加。

     

     

    可能原因:

    1、Object* 没有清理造成的。

    2、vector 较多造成的内存泄漏。

     

    方案1:

    用类对象,然后自己写清理函数:

    加入.clear()一直报错。

     

    后来认为是vector弄得鬼,内存没有释放掉。然后用 .clear() 和 .swap()配合使用。

     

    但是还是会有问题。

    一、人为的管理 Object*

    1先把之前的Object干掉,然后将现在的obs放到last_obs当中去。

    2、将ESR剩下的点,放到Obs当中去。

     

     

    然后,干掉ESR当中加入的Point2D

     

    不过,这种方式不可行,失败了。

     

    二、利用类来管理

    之前,用last_obs = obs; 来进行赋值,直接报错。因为类设计的有问题。之前一直没有注意类里面的复制构造函数以及 = 重载符。

    这些在类里面有vector《T》 ,当T是指针的时候特别有用。因为,这里面会涉及到类的赋值和=。

    比如: OBJ *p1 = other.m.at(i); OBJ*p2 = new OBJ(*p1); ,这里面的OBJ(*p1)就是一个复制构造函数,这个和初始化的构造函数不太一样。

    我们在使用类的时候,最容易犯的错误就是

    int*p = new int(); int*p1 = new int() ; p1 = p; delete p;

    这个时候两个指针是指向的同一块地址,刚开始P1开辟了一块空的地址,但是在p1 = p的时候,此空的地址被P的地址替代。当p被释放的同时,P1也被释放。所以,这种错误一定要避免。

    这个时候,复制构造函数和=重载符,就派上用场了。

    详细的过程参见类:

    Object类对象:

    1. #ifndef OBJECT_H
    2. #define OBJECT_H
    3.  
    4.  
    5. typedef struct Point2dFloat
    6. {
    7.    float x;
    8.    float y;
    9. }Point2dFloat;
    10.  
    11. static bool comp(const Point2dFloat &a, const Point2dFloat &b);
    12.  
    13. class Object //激光雷达数据不用过滤 ,速度值在获取数据的时候得到,计算时间差
    14. {
    15. public:
    16.     Point2dFloat m_objBoxCenter;
    17.  
    18.     Point2dFloat m_relVelocity;
    19.  
    20.     std::vector<Point2dFloat> m_contourPoints;
    21.  
    22.     Point2dFloat getObjBoxCenter() //一线激光雷达中心点,可以设置为 y 坐标的最近点。
    23.     {
    24.        m_objBoxCenter.x = 0;
    25.        m_objBoxCenter.y = 0;
    26.  
    27.        if (m_contourPoints.size() > 1)
    28.        {
    29.           //sort(m_contourPoints.begin(),m_contourPoints.end(),comp);
    30.           //m_objBoxCenter.x = (m_contourPoints[0].x + m_contourPoints[m_contourPoints.size()-1].x)/2;
    31.           //m_objBoxCenter.y = (m_contourPoints[0].y + m_contourPoints[m_contourPoints.size()-1].y)/2;
    32.  
    33.          //根据y去筛选
    34.  
    35.           int cc = 0;
    36.           float y = 10000;
    37.           for (int i = 0; i < m_contourPoints.size(); ++i)
    38.           {
    39.              if (m_contourPoints[i].y < y)
    40.              {
    41.                 y = m_contourPoints[i].y;
    42.                 cc = i;
    43.              }
    44.           }
    45.           m_objBoxCenter.x = m_contourPoints[cc].x;
    46.           m_objBoxCenter.y = m_contourPoints[cc].y;
    47.        }
    48.        else
    49.        {
    50.           m_objBoxCenter.x = m_contourPoints[0].x/2;
    51.           m_objBoxCenter.y = m_contourPoints[0].y/2;
    52.        }
    53.       return m_objBoxCenter;
    54.     }
    55.  
    56.    float m_speed;
    57.  
    58.    //方法2
    59.     Point2dFloat m_pre_objBoxCenter;
    60.     Point2dFloat m_pre_relVelocity; //上一次的数据
    61.  
    62.     Point2dFloat m_next_objBoxCenter;
    63.     Point2dFloat m_next_relVelocity; //预测的数据
    64.  
    65.  
    66.     Object() //初始化构造函数
    67.     {
    68.         m_contourPoints.clear();
    69.     }
    70.  
    71.     Object(const Object& org) //拷贝(复制)构造函数 vector在执行类指针和对象的时候,会调用到此函数
    72.     {
    73.        m_objBoxCenter = org.m_objBoxCenter;
    74.        m_relVelocity = org.m_relVelocity;
    75.        m_contourPoints = org.m_contourPoints;
    76.        m_speed = org.m_speed;
    77.        m_pre_objBoxCenter = org.m_pre_objBoxCenter;
    78.        m_pre_relVelocity = org.m_pre_relVelocity;
    79.        m_next_objBoxCenter = org.m_next_objBoxCenter;
    80.        m_next_relVelocity = org.m_next_relVelocity;
    81.     }
    82.  
    83.     ~Object()//析够函数
    84.     {
    85.        m_contourPoints.clear();
    86.        vector<Point2dFloat>(m_contourPoints).swap(m_contourPoints);//这才是释放内存空间
    87.     }
    88.  
    89. };
    90. bool comp(const Point2dFloat &a, const Point2dFloat &b)
    91. {
    92.    return a.x > b.x; //x 升序
    93. }
    94.  
    95.  
    96. #endif

    管理Object的管理类对象:

    ObjectList 类对象。

    1. #pragma once
    2.  
    3. #include "VirtualSwitchZmq.h"
    4. #include "Object.h"
    5.  
    6. class ObjectList
    7. {
    8.    public:
    9.       ObjectList() //构造函数 参数初始化
    10.       {
    11.          m_objects.clear();
    12.          tick = 0;
    13.       };
    14.  
    15.       ~ObjectList() //析构函数 释放掉其他资源 (关键的地方)
    16.       {
    17.          if (m_objects.size() > 0)
    18.          {
    19.             for (int i = 0; i < m_objects.size(); ++i)
    20.             {
    21.                delete m_objects.at(i);
    22.                m_objects.at(i) = NULL;
    23.             }
    24.             m_objects.clear();
    25.          }
    26.  
    27.       }
    28.  
    29.  
    30.       ObjectList(const ObjectList& other) //复制构造函数
    31.       {
    32.          for (int i = 0; i < other.m_objects.size(); ++i) //将其他类对象深拷贝给当前的对象。
    33.          {
    34.             Object* p1 = other.m_objects.at(i);
    35.             Object* p2 = new Object(*p1); //注意:类里面还有类的话,也需要支持复制构造函数
    36.             m_objects.push_back(p2);
    37.          }
    38.          tick = other.tick; //深拷贝包括其他成员变量
    39.       }
    40.  
    41.       ObjectList &operator=(const ObjectList& other) //重载=符
    42.       {
    43.          if (&other != this) //不同的对象
    44.          {
    45.             for (int i = 0; i < m_objects.size(); ++i) //先释放掉之前开辟的指针,并将指针置空。
    46.             {
    47.                delete m_objects.at(i);
    48.                m_objects.at(i) = NULL;
    49.             }
    50.             m_objects.clear(); //空间置0.
    51.  
    52.             for (int i = 0; i < other.m_objects.size(); ++i) // 将其他类对象赋值给本身的类对象,注意返回的是类对象,而不是类指针。
    53.             {
    54.                Object*p1 = other.m_objects.at(i); //当我们用指针间进行=的时候,需要*p = *q; 这样写才是规范的。
    55.                Object*p2 = new Object(*p1);
    56.                m_objects.push_back(p2);
    57.             }
    58.             tick = other.tick;
    59.          }
    60.          return *this;
    61.       }
    62.  
    63.       void addElem(Object* elem) //封装m_objects,利用函数进行元素的增加和减少
    64.       {
    65.          m_objects.push_back(elem);
    66.       }
    67.  
    68.       int getSize()
    69.       {
    70.          return m_objects.size();
    71.       }
    72.  
    73.       std::vector<Object*> m_objects;
    74.    //同步到ms
    75.       long tick;
    76. };

     

    目前上面的封装还是有些问题,后面需要根据需要再修改。

     

    调用:

    刚开始清零,然后赋值给上一个last_obs,然后将obs释放掉。

     

     

    三、换用智能指针

    Shared_ptr<> (); make_share<>(); 成对使用。

    管理动态创建的对象的销毁,原理是记录对象被引用的 次数。

    Std::tr1 或者 boost:: 里面都有,假如同时加入两个命名空间。需要指明命名空间。

    目前还没有掌握好如何正确使用智能指针,但是对于上面的问题,不知道用智能指针如何上手,后续增加相关功能。

     

  • 相关阅读:
    我是新手,我在学Android
    WAMP环境下(apache2.2.21+Php5.3.10)编写PHP扩展
    java中三种字符串正则匹配方式
    PHP扩展开发过程中的问题
    Android错误解决方法之:Debug certificate expired on
    Ubuntu下C++开发PHP开发扩展的注意事项
    我的笔试题
    很多时候,是否好好看完一本好书,对一个人的提升往往能达到质的区别
    C语言常用宏定义
    Linux下用C++开发PHP扩展
  • 原文地址:https://www.cnblogs.com/zhuxuekui/p/6002414.html
Copyright © 2011-2022 走看看