先上代码
/*
C++构造\析构\赋值\函数调用
by cjc
2014/3/27
*/
#include<iostream>
using namespace std;
class B
{
public:
B():data(0)
{
cout<<"default constructor"<<endl;
}
~B()
{
cout<<"destructed by parameter "<<data<<endl;
}
B(int i):data(i)
{
cout<<"constructed by parameter "<<data<<endl;
}
B(B &b)
{
data=b.data;
cout<<"copyed by parameter "<<data<<endl;
}
B& operator =(const B &b)
{
this->data=b.data;
cout<<"= by parameter "<<data<<endl;
return *this;
}
private:
int data;
};
B Play(B b)
{
return b;
}
void main(void)
{
Play(1);
B t1=Play(2);
B t2;
t2=Play(3);
return;
}这里先不解释上面的结果,首先补充一下C语言函数调用的东西。
明确几个问题:
为什么不是其它类型变量呢?比如说全局变量……额,明显不可能是这样的,之所以是局部变量,可以通过学习C语言时美女老师讲解的“值传递和指针传递”的问题来理解。既然是局部变量那么在函数调用时,形式参数是怎样传递的呢?学习过C语言的都知道,通过实参拷贝构造了形式参数,即将一个程序空间的局部变量传递给另外的一个程序空间。局部变量的生命期是所在函数的生命期。
同样是两个程序空间传值问题。一般来说, 局部变量的作用域只在所属函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错,因为在返回的时候传递的是复制后的局部变量,即一个副本。但是如果返回的是局部变量的地址(指针)的话,程序运行后一般会出错。因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,即野指针,这样指针指向的内容就是不可预料的东东,调用就会出错。准确的来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的)。
下面以函数返回局部变量的指针举几个典型的例子来说明:
#include <stdio.h>
#include <stdlib.h>
char* func(void)
{
char* p="cjc is a good boy";
return p;
}
int main(void)
{
char* str;
str=func();
printf("%s\n",str);
system("pause");
return 0;
}#include <stdio.h>
#include <stdlib.h>
char* func(void)
{
char p[]="cjc is a good boy";
return p;
}
int main(void)
{
char* str;
str=func();
printf("%s\n",str);
system("pause");
return 0;
}#include <stdio.h>
#include <stdlib.h>
char* func(void)
{
static char p[]="cjc is a good boy";
return p;
}
int main(void)
{
char* str;
str=func();
printf("%s\n",str);
system("pause");
return 0;
}#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* func(void)
{
char p[]="cjc is a good boy";
char* str;
str=(char*)malloc(sizeof(char)*20);
strcpy(str,p);
return str;
}
int main(void)
{
char* str;
str=func();
printf("%s\n",str);
system("pause");
return 0;
}首先传递参数1给Play函数,由于Play函数的形参是B类型,因此调用B相应的构造函数生成对象b,当执行return b;时,调用copy构造函数生成传回的对象(复制品),随即函数结束,局部变量b被析构,由于传回的复制对象,在主程序中没有承载的载体,故马上被析构。
与1中不同的是,此时传回的对象是由对象t1来承载的,故传回的复制品的生命期与t1相同,在主程序结束时析构。这里"="并非赋值,因为t1在函数Play(2)返回时并不存在,t1在这里起到一个承接返回值的作用,与此同时构建自己。
函数的分析与上面完全相同,这里"="是赋值操作,调用赋值函数,原因是t2是原来已经存在的对象。最后的两个"destructed by parameter 3"一个是Play(3)返回的复制品的析构,一个是t2的析构。
本文第二部分参考了参考1
C++构造函数、拷贝构造函数、赋值函数、析构函数在函数调用中的使用过程,布布扣,bubuko.com
C++构造函数、拷贝构造函数、赋值函数、析构函数在函数调用中的使用过程
原文:http://blog.csdn.net/cjc211322/article/details/22313393