一个关于vector中push_back()方法的小问题

HengStar 2008-03-09 12:56:39
我在定义了一个CTest类后用来测试vector,在CTest的析构函数中加入了输出语句
主类中代码如下
[code=C/C++]
CTest me;
CTest me1("ok", 2);
//me.Print();
vector<CTest> tvec;

tvec.push_back(me); //此句执行完后调用CTest的析构一次
tvec.push_back(me1); //此句执行完后调用CTest的析构两次
tvec.push_back(me1);
//此句执行完后调用CTest的析构三次
cout << "test" << endl; //在此语句输出前已经调用了6次(1+2+3)CTest的析构函数 vector<CTest> tvec1(tvec);

(++tvec1.begin())->Print();
[code]
也就是说每push_back一个元素就会都要析构size次该vector中的元素(size为vector的长度),如果每次push_back(element)是将element作为副本拷贝给vector中的新元素,并释放(析构)element,那么按理说每次push_back()都只会析构一次,但为什么是这种情况呢?费解...难道每次push_back()都要将vector中的所有元素都重新赋值一次并释放所有副本?求解!
...全文
337 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
linfengc 2008-03-09
  • 打赏
  • 举报
回复
拷贝构造的问题。
HengStar 2008-03-09
  • 打赏
  • 举报
回复
非常感谢akirya的解答~
HengStar 2008-03-09
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 arong1234 的回复:]
作为“新手”,我就不知道了
[/Quote]

不好意思~在这里我没有贬低你的意思,谢谢你耐心的帮我解答,如有不是还望多多包涵,呵呵

我还是把完整源代码帖出来吧~
头文件Test.h

#pragma once
using namespace std;
class CTest
{
public:
CTest();
CTest(string name, int id);
~CTest();
inline void Print() const
{
cout << "id = " << id << "\tname = " << name << endl;
}

string name;
int id;
};


源文件

#include <iostream>
#include <vector>
#include <string>
#include "Test.h"


CTest::CTest():name("no name"), id(-1)
{
}

CTest::CTest(string name, int id):name(name), id(id)
{
}

CTest::~CTest()
{
cout << "destructed" << endl;
}

int main()
{
CTest me;
CTest me1("ok", 2);

//me.Print();
vector<CTest> tvec;
tvec.push_back(me);

tvec.push_back(me1);

tvec.push_back(me1);
cout << "test" << endl;

vector<CTest> tvec1(tvec);

(++tvec1.begin())->Print();
list< deque<int> > myList;
return 0;
}
  • 打赏
  • 举报
回复
测试代码如下

#include<iostream>
#include<vector>
using namespace std;

class CTest
{

public:
CTest(){}
CTest(const char* x,int i){}
~CTest()
{
cout<<"CTest::~CTest"<<endl;
}
};

int main(int argc,char* argv[])
{

CTest me;
CTest me1("ok", 2);

{
vector <CTest> tvec;
tvec.push_back(me);
cout<<"111"<<endl;
tvec.push_back(me1);
cout<<"222"<<endl;
tvec.push_back(me1);
cout<<"333"<<endl;
}
cout<<"================"<<endl;
{
vector <CTest> tvec;
tvec.reserve( 3);
tvec.push_back(me);
cout<<"111"<<endl;
tvec.push_back(me1);
cout<<"222"<<endl;
tvec.push_back(me1);
cout<<"333"<<endl;
}
cout<<"================"<<endl;
return 0;
}


VC6结果
111
CTest::~CTest
222
CTest::~CTest
CTest::~CTest
333
CTest::~CTest
CTest::~CTest
CTest::~CTest
================
111
222
333
CTest::~CTest
CTest::~CTest
CTest::~CTest
================
CTest::~CTest
CTest::~CTest

VC8结果
CTest::~CTest
111
CTest::~CTest
CTest::~CTest
222
CTest::~CTest
CTest::~CTest
CTest::~CTest
333
CTest::~CTest
CTest::~CTest
CTest::~CTest
================
111
222
333
CTest::~CTest
CTest::~CTest
CTest::~CTest
================
CTest::~CTest
CTest::~CTest


g++ 4.2.1结果
111
CTest::~CTest
222
CTest::~CTest
CTest::~CTest
333
CTest::~CTest
CTest::~CTest
CTest::~CTest
================
111
222
333
CTest::~CTest
CTest::~CTest
CTest::~CTest
================
CTest::~CTest
CTest::~CTest


BCC 5.9结果
111
CTest::~CTest
222
CTest::~CTest
CTest::~CTest
333
CTest::~CTest
CTest::~CTest
CTest::~CTest
================
111
222
333
CTest::~CTest
CTest::~CTest
CTest::~CTest
================
CTest::~CTest
CTest::~CTest


结论我上面说过了不重复了
ochinchina 2008-03-09
  • 打赏
  • 举报
回复
只有当vector的空间耗完以后,vector重新分配空间才会将老的CTest拷贝进新的重新分配的空间中,并将老空间中的CTest删除。如果在构造vector的时候给它指定空间大小,如vector<CTest> tvec(16),你的问题就不会出现
arong1234 2008-03-09
  • 打赏
  • 举报
回复
从代码上,作为新手,我还是说不应该析构,除非有优化的结果,禁止优化去检查一下也许比较直观
如果这还不能释疑,没说的,在调试器执行,单步跟踪一下不就知道了
HengStar 2008-03-09
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 arong1234 的回复:]
CTest me;
CTest me1("ok", 2);
//me.Print();
vector <CTest> tvec;

tvec.push_back(me); //vector在push_back(me)时会把me拷贝到自己结构中,创建一个克隆体
tvec.push_back(me1); //vector在push_back(me1)时会把me1拷贝到自己结构中,创建一个克隆体
tvec.push_back(me1); //ditto
cout < < "test" < < endl;//此时系统已经出现5个CTest对象,包括在ve…
[/Quote]

如果我这样写
tvec.push_back(me);
tvec.push_back(me1);
cout << "test" << endl;
tvec.push_back(me1);

那么在输出test 前会执行3次CTest析构

这样写
tvec.push_back(me);
tvec.push_back(me1);
tvec.push_back(me1);
cout << "test" << endl;

那么在输出test 前会执行6次CTest析构

这样写
tvec.push_back(me);
tvec.push_back(me1);
tvec.push_back(me1);
tvec.push_back(me1);
cout << "test" << endl;

那么在输出test 前会执行10次CTest析构

也就是每次push_back,析构的次数会在前次的基础上累加1
(++tvec1.begin())->Print(); //调用该迭代器指向的vector对象的第二个元素的Print()方法
arong1234 2008-03-09
  • 打赏
  • 举报
回复
作为“新手”,我就不知道了
HengStar 2008-03-09
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 arong1234 的回复:]
比较怀疑楼主说的已经析构多少此的说法,因为此时一个对象都不应该析构。这可能和你CTest的设计有关,也可能和你判断的方式有关。,你怎么知道它已经析构的?
[/Quote]

这位同志是新手吧...
我在CTest析构函数中用了cout << "destructed" << endl;
所以每次析构都会打印出destructed
arong1234 2008-03-09
  • 打赏
  • 举报
回复
比较怀疑楼主说的已经析构多少此的说法,因为此时一个对象都不应该析构。这可能和你CTest的设计有关,也可能和你判断的方式有关。,你怎么知道它已经析构的?
arong1234 2008-03-09
  • 打赏
  • 举报
回复
CTest me;
CTest me1("ok", 2);
//me.Print();
vector <CTest> tvec;

tvec.push_back(me); //vector在push_back(me)时会把me拷贝到自己结构中,创建一个克隆体
tvec.push_back(me1); //vector在push_back(me1)时会把me1拷贝到自己结构中,创建一个克隆体
tvec.push_back(me1); //ditto
cout < < "test" < < endl;//此时系统已经出现5个CTest对象,包括在vector中的

vector <CTest> tvec1(tvec); //此时又复制出5个

(++tvec1.begin())-> Print(); //这一句啥意思?begin返回的变量能++?
HengStar 2008-03-09
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 dead_of_winter 的回复:]
CTest是不是太大了?
[/Quote]

-.-怎么可能跟这个有关系...
dead_of_winter 2008-03-09
  • 打赏
  • 举报
回复
CTest是不是太大了?
rularys 2008-03-09
  • 打赏
  • 举报
回复
"难道每次push_back()都要将vector中的所有元素都重新赋值一次并释放所有副本?求解!"

应该不会有这样低效的实现;基本上都是在容器本身预留的空间被用完以后,容器才会从新申请空间并将原内容拷贝过去
  • 打赏
  • 举报
回复
那些就要看实现了,每次增加元素的时候都有可能引起重新分配内存,元素拷贝的过程.

不过建议预先分配vector所需要的内存
调用Reserves

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧