关于析构函数和临时对象,问题解决立刻结贴

fangxishanglu 2007-12-10 11:14:20
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:

Student(string ,string ,int);
~Student();
void display();
public:
string name;
string sex;
int age;
};

Student::Student(string n,string s,int a)
{
name=n; //学生姓名
sex=s; //学生性别
age=a; //学生年龄
}

Student::~Student()
{
cout << "调用析构函数" << endl ;
}

void Student::display()
{
cout << name << "//" << sex << "//" << age << endl ;
}
int main()
{
Student s[3]={Student("a","b",1),Student("a1","b",10),Student("a3","b",100)};
s[0].display();
s[1].display();
s[2].display();
return 0;
}



为什么析构函数调用了六次,我只创建了3个对象实例,觉得应该是数组定义的时候建立了3个临时对象(猜测^_^)
什么时候需要临时对象,为什么要?
有答案立刻给分,不够可以加
最好可以解释清楚程序在内存中干了什么……
...全文
414 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
小函数 2011-02-09
  • 打赏
  • 举报
回复
俺也是用的VC++6 但是俺把楼主那个代码跑了一次没结果是调用了三次析构函数,汗,7楼的说法俺赞同,类似
X a=X(1);这种语法的确是X(1)先产生一个临时对象然后通过内存复制复制到a中去的,但是我敢说VC6的却是做了优化,push给X构造函数的那个地址直接就是a的地址,都是这样的,所以这里没有产生临时量,难道大家用的vc还不一样?好乱,关于临时量这个问题还要继续研究总结一下-_-!
做鸡真好吃 2007-12-11
  • 打赏
  • 举报
回复
?
独孤过儿 2007-12-10
  • 打赏
  • 举报
回复
to LZ: you should read the articles about constructor, destructor, copy constructor and assignment.

to ctk: you are a star now! ~_~ Congratulations!
fangxishanglu 2007-12-10
  • 打赏
  • 举报
回复
呵呵,单步追踪调试过了,不是很懂才来问问的,学了不少
学C++比学C烦很多-_-
ryfdizuo 2007-12-10
  • 打赏
  • 举报
回复
lz可以单步追踪调试一下,
眼见为实嘛,
^_^
yydrewdrew 2007-12-10
  • 打赏
  • 举报
回复
#include   <iostream> 
#include <string>
using namespace std;
class Student
{
public:
Student(string,string,int);
~Student();
Student(const Student&obj);
void display();
public:
string name;
string sex;
int age;
};

Student::Student(string n,string s,int a)
{
cout<<"construct"<<endl;
name=n; //学生姓名
sex=s; //学生性别
age=a; //学生年龄
}
Student::Student(const Student& obj)
{
cout<<"copy construct"<<endl;
}
Student::~Student()
{
cout<<"调用析构函数"<<endl;
}

void Student::display()
{
cout<<name<<"//"<<sex<<"//"<<age<<endl;
}
int main()
{
Student s[3]={Student("a","b",1),Student("a1","b",10),Student("a3","b",100)};
return 0;
}

像这样初始化数组都有一个拷贝过程
比如
char  a[] = "12345";
是栈里分配一个char[6]的数组,把字符串"12345"从常量数据区拷贝过来
程序中只不过是通过构建临时变量再拷贝到栈里Student s[3]数组里。
函数按值返回也会构建临时变量
还有这种:
f(int a){};//定义
f(int(14));//调用

也构建了一个int临时变量
lynnboy 2007-12-10
  • 打赏
  • 举报
回复
见C++标准 8.5初始化式 8.5.1聚合

聚合初始化语义其实等同于初始化语义。也就是说,
Student   s[3]={Student("a","b",1),Student("a1","b",10),Student("a3","b",100)}; 

差不多相当于
Student   s0=Student("a","b",1);
Student s1=Student("a1","b",10);
Student s2=Student("a3","b",100);

上面这种初始化语法,在语义上算作“复制初始化”。先构造一个临时对象,在用这个对初始化的对象进行复制构造。
虽然理论上编译器可以消除这个临时对象(算作一种优化),但VC6应该没有这么作。

skytiger_z 2007-12-10
  • 打赏
  • 举报
回复


数组是静态数据结构,因此创建的时候就需要分配内存,这个对象数组的建立是同样的道理,作为临时对象创建了,因此调用了三次析构函数.见笑了~~
飞哥 2007-12-10
  • 打赏
  • 举报
回复
Student("a","b",1)
Student("a1","b",10)
Student("a3","b",100)
分别产生一个临时对象,为s[3]赋初值
他们的作用域在{}内,出了{}就被释放掉了
tcxjia 2007-12-10
  • 打赏
  • 举报
回复
s[0].display();
s[1].display();
s[2].display();
创建临时对象,调用拷贝构造函数没计算进去
bs2x418 2007-12-10
  • 打赏
  • 举报
回复
还真没发现,学习下MARK
ckt 2007-12-10
  • 打赏
  • 举报
回复
临时对象的资料,你可以参考
http://www.cpper.com/c/p12856_1.html
ckt 2007-12-10
  • 打赏
  • 举报
回复
和你猜测的一样,中间产生了三个临时变量,
然后调用拷贝构造初始化对象数组的元素
你可以在构造函数,拷贝构造函数里添加输出查看下


#include <iostream>
#include <string>
using namespace std;
class Student
{
public:

Student(string ,string ,int);
Student(const Student& s);
~Student();
void display();
public:
string name;
string sex;
int age;
};

Student::Student(string n,string s,int a)
{
name=n; //学生姓名
sex=s; //学生性别
age=a; //学生年龄
cout << "调用构造函数" << endl ;
}

Student::Student(const Student& s)
{
name = s.name;
sex = s.sex;
age = s.age;
cout << "调用拷贝构造函数" << endl ;

}

Student::~Student()
{
cout << "调用析构函数" << endl ;
}

void Student::display()
{
cout << name << "//" << sex << "//" << age << endl ;
}

int main()
{
Student s[3] = {Student("a","b",1), Student("a1","b",10), Student("a3","b",100)};
s[0].display();
s[1].display();
s[2].display();
return 0;
}

sinux_1983 2007-12-10
  • 打赏
  • 举报
回复
受教了。
整理一下,收藏到邮箱里。
bigc2000 2007-12-10
  • 打赏
  • 举报
回复
说一下,
这个copy是堆对象copy到栈上,其实这中情况还出现在
函数返回引用时,处理不好也会这样,而且内存泄漏。



//-----------------解决之道------------------
//申请内存供待会使用
void *rawMemory = operator new(10*sizeof(Student));
这种方式,不建议使用,因为如果存在虚函数,析构时会出错

最好还是用指针来处理,
其实C++不赞成使用指针的想法是不可能实现的,很多情况,最好的解决办法,都是指针
fangxishanglu 2007-12-10
  • 打赏
  • 举报
回复
to:Jerry_Chow
讲得很清楚,仰视中.....
分你得一半^_^
zhangystc 2007-12-10
  • 打赏
  • 举报
回复
up,and mark
ltc_mouse 2007-12-10
  • 打赏
  • 举报
回复
标记下,学习~
taodm 2007-12-10
  • 打赏
  • 举报
回复
to楼上,自己找个编译器试一下。
如果书错了,就换本好点的。
实践出真知。
cwbcwb505 2007-12-10
  • 打赏
  • 举报
回复
看了以上程序后让我感到有些迷惑,因为我在书上看到没有默认构造函数的类数组不能初始化,上述程序好像违背了这句话,望大蛱指点
加载更多回复(10)

64,652

社区成员

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

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