vector中使用拷贝构造函数和解除const的关键字const_cast介绍
2017-05-12 14:14
369 查看
一、深拷贝和浅拷贝
浅拷贝,假如在定义一个类A,然后使用类似A obj; A obj1(obj);或者A obj1 = obj; 时候,由于没有自定义拷贝构造函数,C++编译器自动会产生一个默认的拷贝构造函数。这个默认的拷贝构造函数采用的是“位拷贝”(浅拷贝),而非“值拷贝”(深拷贝)的方式,如果类中含有指针变量,默认的拷贝构造函数必定出错。
浅拷贝:只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,
深拷贝:不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
举一个例子,当我使用vetcor<T>obj申明一个obj容器之后,obj.push_back(obj1)此时就会调用浅拷贝,但是这样会带来一个严重的问题:当obj1释放掉内部的指针时,obj[0]内部的指针也被释放掉了,这样就会产生野指针。
二、vector和拷贝构造函数
vector其中一个特点:内存空间只会增长,不会减小,援引C++ Primer:为了支持快速的随机访问,vector容器的元素以连续方式存放,每一个元素都紧挨着前一个元素存储。设想一下,当vector添加一个元素时,为了满足连续存放这个特性,都需要重新分配空间、拷贝元素、撤销旧空间,这样性能难以接受。因此STL实现者在对vector进行内存分配时,其实际分配的容量要比当前所需的空间多一些。就是说,vector容器预留了一些额外的存储区,用于存放新添加的元素,这样就不必为每个新元素重新分配整个容器的内存空间。
在调用push_back时,每次执行push_back操作,相当于底层的数组实现要重新分配大小;这种实现体现到vector实现就是每当push_back一个元素,都要重新分配一个大一个元素的存储,然后将原来的元素拷贝到新的存储,之后在拷贝push_back的元素,最后要析构原有的vector并释放原有的内存。例如下面程序:
输出结果:
其中执行
此时vector会申请一个内存空间,并调用拷贝构造函数将a放到vector中
再调用
此时内存不够 需要扩大内存,重新分配内存 这时再调用拷贝构造函数将a拷贝到新的内存,再将b拷入新的内存,同时有人调用Point拷贝构造函数,最后释放原来的内存 此时调用Point的析构函数。
注:当释放vector的时候,用clear只能清空vector的内容,而不释放内存,所以需要使用erase。
三、消除const修饰对象时带来错误
当我们使用拷贝构造函数的时候,参数内必须用const修饰,此时如果调用该对象的方法时,就会报出这样的错误:
对象引用前加const报错:不能将“this”指针从“const a”转换为“a &”
解决方法看别人的博客发现有三种方法:
1. 解决方法一:不使用const
2. 使用const_cast<Class *>(ptr),进行相应的转化
3.将相关的函数转化成相应的const函数
c++新手,如果有不对的地方希望能帮忙指正,多谢。
浅拷贝,假如在定义一个类A,然后使用类似A obj; A obj1(obj);或者A obj1 = obj; 时候,由于没有自定义拷贝构造函数,C++编译器自动会产生一个默认的拷贝构造函数。这个默认的拷贝构造函数采用的是“位拷贝”(浅拷贝),而非“值拷贝”(深拷贝)的方式,如果类中含有指针变量,默认的拷贝构造函数必定出错。
浅拷贝:只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,
深拷贝:不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
举一个例子,当我使用vetcor<T>obj申明一个obj容器之后,obj.push_back(obj1)此时就会调用浅拷贝,但是这样会带来一个严重的问题:当obj1释放掉内部的指针时,obj[0]内部的指针也被释放掉了,这样就会产生野指针。
二、vector和拷贝构造函数
vector其中一个特点:内存空间只会增长,不会减小,援引C++ Primer:为了支持快速的随机访问,vector容器的元素以连续方式存放,每一个元素都紧挨着前一个元素存储。设想一下,当vector添加一个元素时,为了满足连续存放这个特性,都需要重新分配空间、拷贝元素、撤销旧空间,这样性能难以接受。因此STL实现者在对vector进行内存分配时,其实际分配的容量要比当前所需的空间多一些。就是说,vector容器预留了一些额外的存储区,用于存放新添加的元素,这样就不必为每个新元素重新分配整个容器的内存空间。
在调用push_back时,每次执行push_back操作,相当于底层的数组实现要重新分配大小;这种实现体现到vector实现就是每当push_back一个元素,都要重新分配一个大一个元素的存储,然后将原来的元素拷贝到新的存储,之后在拷贝push_back的元素,最后要析构原有的vector并释放原有的内存。例如下面程序:
#include <iostream> #include <cstdlib> #include <vector> using namespace std; class Point { public: Point() { cout << "construction" << endl; } Point(const Point& p)//拷贝构造函数 { cout << "copy construction" << endl; } ~Point() { cout << "destruction" << endl; } }; int main() { vector<Point> pointVec; Point a; Point b; pointVec.push_back(a); pointVec.push_back(b); cout<<pointVec.size()<<std::endl; return 0; }
输出结果:
其中执行
pointVec.push_back(a);
此时vector会申请一个内存空间,并调用拷贝构造函数将a放到vector中
再调用
pointVec.push_back(b);
此时内存不够 需要扩大内存,重新分配内存 这时再调用拷贝构造函数将a拷贝到新的内存,再将b拷入新的内存,同时有人调用Point拷贝构造函数,最后释放原来的内存 此时调用Point的析构函数。
注:当释放vector的时候,用clear只能清空vector的内容,而不释放内存,所以需要使用erase。
三、消除const修饰对象时带来错误
当我们使用拷贝构造函数的时候,参数内必须用const修饰,此时如果调用该对象的方法时,就会报出这样的错误:
对象引用前加const报错:不能将“this”指针从“const a”转换为“a &”
解决方法看别人的博客发现有三种方法:
1. 解决方法一:不使用const
2. 使用const_cast<Class *>(ptr),进行相应的转化
A * b = const_cast<A*>(obj); //obj代表实际应该使用的对象,此时用一个新对象b来消除const限定 b->GetIt();//编译就没错了
3.将相关的函数转化成相应的const函数
class A { int m_It; public: int GetIt() const; } int A::GetIt() const//这个地方也要加const { return m_It; }附上项目中遇到这个问题,解决之后的主要代码
Action::Action(const Action &action) //拷贝构造函数,进行深拷贝 { EffeciencyState* pEffeciencyState = NULL; Action* pAction = const_cast<Action*>(&action); //解决const限定 for(int i = 0; i < pAction->getEffeciencyStateList().length(); i++) { if(pAction->getEffeciencyStateList()[i]->getType() == normal) { pEffeciencyState = new EffeciencyState(); pEffeciencyState->setEffeciencyStateName(pAction->getEffeciencyStateList()[i]->getEffeciencyStateName()); pEffeciencyState->setEffeciencyStateTime(pAction->getEffeciencyStateList()[i]->getEffeciencyStateTime()); pEffeciencyState->setDescription(pAction->getEffeciencyStateList()[i]->getDescription()); } else { pEffeciencyState = new HttpRequest(); pEffeciencyState->setEffeciencyStateName(pAction->getEffeciencyStateList()[i]->getEffeciencyStateName()); pEffeciencyState->setEffeciencyStateTime(pAction->getEffeciencyStateList()[i]->getEffeciencyStateTime()); pEffeciencyState->setDescription(pAction->getEffeciencyStateList()[i]->getDescription()); pEffeciencyState->setDuringTime(pAction->getEffeciencyStateList()[i]->getDuringTime()); } m_oEffeciencyStateList.push_back(pEffeciencyState); } m_sActionName = pAction->getActionName(); m_bVisitState = pAction->getVisitState(); m_oBeginTime = pAction->getBeginTime(); m_oEndTime = pAction->getEndTime(); m_oStateNumberMap = pAction->getStateNumberMap(); m_oStepActionList = pAction->getStepActionList(); }
c++新手,如果有不对的地方希望能帮忙指正,多谢。
相关文章推荐
- C++ 关键字的使用(const static explict reinterpret_cast)
- 黑马程序员-C语言回顾-const关键字介绍及使用
- c++中const关键字使用详解
- 关键字Const与Volatile的使用
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast
- const关键字的使用
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterdivt_cast、和const_cast
- 转:关键字Const和Volatile的使用
- 使用const关键字进行函数重载
- C#中using关键字的使用介绍
- C语言const介绍(const关键字说明)
- php面向对象全攻略 (十) final static const关键字的使用
- C++中”const“关键字使用详解
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast。(转)
- 使用标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast。(转)
- 标准c++中四种强制转换类型运算符介绍 const_cast,reinterpret_cast,static_cast,dynamic_cast
- const_cast的使用方法
- 被迫使用const_cast
- C++ 中 const 关键字使用详解
- C 语言中 const 关键字介绍