标签:定义 资料 points list enter ast 记录 析构 ret
参考资料:
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类对象:
#ifndef OBJECT_H
#define OBJECT_H
typedef struct Point2dFloat
{
float x;
float y;
}Point2dFloat;
static
bool comp(const Point2dFloat &a, const Point2dFloat &b);
class Object //激光雷达数据不用过滤 ,速度值在获取数据的时候得到,计算时间差
{
public:
Point2dFloat m_objBoxCenter;
Point2dFloat m_relVelocity;
std::vector<Point2dFloat> m_contourPoints;
Point2dFloat getObjBoxCenter() //一线激光雷达中心点,可以设置为 y 坐标的最近点。
{
m_objBoxCenter.x = 0;
m_objBoxCenter.y = 0;
if (m_contourPoints.size() > 1)
{
//sort(m_contourPoints.begin(),m_contourPoints.end(),comp);
//m_objBoxCenter.x = (m_contourPoints[0].x + m_contourPoints[m_contourPoints.size()-1].x)/2;
//m_objBoxCenter.y = (m_contourPoints[0].y + m_contourPoints[m_contourPoints.size()-1].y)/2;
//根据y去筛选
int cc = 0;
float y = 10000;
for (int i = 0; i < m_contourPoints.size(); ++i)
{
if (m_contourPoints[i].y < y)
{
y = m_contourPoints[i].y;
cc = i;
}
}
m_objBoxCenter.x = m_contourPoints[cc].x;
m_objBoxCenter.y = m_contourPoints[cc].y;
}
else
{
m_objBoxCenter.x = m_contourPoints[0].x/2;
m_objBoxCenter.y = m_contourPoints[0].y/2;
}
return m_objBoxCenter;
}
float m_speed;
//方法2
Point2dFloat m_pre_objBoxCenter;
Point2dFloat m_pre_relVelocity; //上一次的数据
Point2dFloat m_next_objBoxCenter;
Point2dFloat m_next_relVelocity; //预测的数据
Object() //初始化构造函数
{
m_contourPoints.clear();
}
Object(const Object& org) //拷贝(复制)构造函数 vector在执行类指针和对象的时候,会调用到此函数
{
m_objBoxCenter = org.m_objBoxCenter;
m_relVelocity = org.m_relVelocity;
m_contourPoints = org.m_contourPoints;
m_speed = org.m_speed;
m_pre_objBoxCenter = org.m_pre_objBoxCenter;
m_pre_relVelocity = org.m_pre_relVelocity;
m_next_objBoxCenter = org.m_next_objBoxCenter;
m_next_relVelocity = org.m_next_relVelocity;
}
~Object()//析够函数
{
m_contourPoints.clear();
vector<Point2dFloat>(m_contourPoints).swap(m_contourPoints);//这才是释放内存空间
}
};
bool comp(const Point2dFloat &a, const Point2dFloat &b)
{
return a.x > b.x; //x 升序
}
#endif
管理Object的管理类对象:
ObjectList 类对象。
#pragma once
#include "VirtualSwitchZmq.h"
#include "Object.h"
class ObjectList
{
public:
ObjectList() //构造函数 参数初始化
{
m_objects.clear();
tick = 0;
};
~ObjectList() //析构函数 释放掉其他资源 (关键的地方)
{
if (m_objects.size() > 0)
{
for (int i = 0; i < m_objects.size(); ++i)
{
delete m_objects.at(i);
m_objects.at(i) = NULL;
}
m_objects.clear();
}
}
ObjectList(const ObjectList& other) //复制构造函数
{
for (int i = 0; i < other.m_objects.size(); ++i) //将其他类对象深拷贝给当前的对象。
{
Object* p1 = other.m_objects.at(i);
Object* p2 = new Object(*p1); //注意:类里面还有类的话,也需要支持复制构造函数
m_objects.push_back(p2);
}
tick = other.tick; //深拷贝包括其他成员变量
}
ObjectList &operator=(const ObjectList& other) //重载=符
{
if (&other != this) //不同的对象
{
for (int i = 0; i < m_objects.size(); ++i) //先释放掉之前开辟的指针,并将指针置空。
{
delete m_objects.at(i);
m_objects.at(i) = NULL;
}
m_objects.clear(); //空间置0.
for (int i = 0; i < other.m_objects.size(); ++i) // 将其他类对象赋值给本身的类对象,注意返回的是类对象,而不是类指针。
{
Object*p1 = other.m_objects.at(i); //当我们用指针间进行=的时候,需要*p = *q; 这样写才是规范的。
Object*p2 = new Object(*p1);
m_objects.push_back(p2);
}
tick = other.tick;
}
return *this;
}
void addElem(Object* elem) //封装m_objects,利用函数进行元素的增加和减少
{
m_objects.push_back(elem);
}
int getSize()
{
return m_objects.size();
}
std::vector<Object*> m_objects;
//同步到ms
long tick;
};
目前上面的封装还是有些问题,后面需要根据需要再修改。
调用:
刚开始清零,然后赋值给上一个last_obs,然后将obs释放掉。
三、换用智能指针
Shared_ptr<> (); make_share<>(); 成对使用。
管理动态创建的对象的销毁,原理是记录对象被引用的 次数。
Std::tr1 或者 boost:: 里面都有,假如同时加入两个命名空间。需要指明命名空间。
目前还没有掌握好如何正确使用智能指针,但是对于上面的问题,不知道用智能指针如何上手,后续增加相关功能。
类的再理解
标签:定义 资料 points list enter ast 记录 析构 ret
原文地址:http://www.cnblogs.com/zhuxuekui/p/6002414.html