最近笔试总结一
来源:互联网 发布:java实现加法器 编辑:程序博客网 时间:2024/06/06 01:15
问题一:复制构造函数
参数的传递方式有两种:传值调用和传址调用。
传值调用的时候,传送的是作为实际参数的对象的副本而不是实际对象本身
- #include<iostream>
- using namespace std;
- class square
- {
- int side;
- public:
- square(int x)
- {
- side=x;
- cout<<"constructiong\n";
- }
- ~square()
- {
- cout<<"Destructiong"<<"\n";
- }
- void display()
- {
- cout<<side<<"\n";
- }
- };
- void f(square ob)
- {
- ob.display();
- }
- int main()
- {
- square s(10);
- f(s);//对象s以传值方式给临时对象x
- s.display();
- return 0;
- }
Constructiong
10
Destructiong
10
Destructiong
为什么构造函数执行一次,而析构函数执行两次呢?
当一个对象被作为参数传递给函数的时候,同时也创建了该对象的副本。(这个副本才是函数的参数)这就是说:创建了一个新的对象。当函数结束的时候,作为函数的实际参数的副本也将被销毁,这产生的问题有:
(1)在创建对象的副本的时候是否调用了构造函数?
(2)在销毁对象的副本的时候是否调用了析构函数?
首先,在调用函数的时候,程序创建了一个对象的副本作为形式参数,此时普通的构造函数并没有调用。而是调用了复制构造函数。如上代码所示:创建形式参数ob的时候,是通过square类的复制构造函数进行传参数的,并没有调用用来执行初始化的普通的构造函数square(int x)
复制构造函数定义了如何创建一个对象的副本。
如果一个类中没有显示的定义类的复制构造函数,那么C—++将提供一个默认的复制构造函数。(默认的复制构造函数将以按位复制的形式创建了一个对象的副本)
由于普通的构造函数通常用于初始化对象的某些成员,因此就不能调用普通构造函数创建对象的副本,因为这样产生的对象可能与现在的对象不完全相同。当把一个对象传递给函数的时候,需要使用的是对象的当前状态,而不是初始。
其次,当函数结束的时候, 由于作为参数的对象副本超出了作用域。因此它将被销毁!!从而调用析构函数,这就是为什么前面的程序中调用两次:第一次是因为函数display()的参数超出了作用域,第二次才是因为住函数main()中的对象s在程序结束时候,被销毁。
综上所述:当创建一个对象的副本作为函数的参数的时候,普通的构造函数没有被调用,锁调用的构造函数是按位复制的默认复制构造函数,但是当对象的副本被销毁的时候,常常因为(函数返回而超出作用域),析够函数被调用。
自定义的复制构造函数:
当使用一个对象来初始化另一个对象的时候,也将调用复制构造函数。
eg:什么是自定义的复制构造函数?
- #include<stdlib.h>
- #include<string.h>
- #include<iostream>
- using namespace std;
- class my_string
- {
- char *s;
- public:
- my_string(char*str);//构造函数
- my_string(const my_string&obj);//自定义的复制构造函数
- ~my_string()
- {
- if(s)
- delete [] s;
- cout<<"Freeing s\n";
- }
- void show()
- {
- cout<<s<<"\n";
- }
- };
- my_string::my_string(char*str)
- {
- s=new char[strlen(str)+1];
- cout<<"Allocating room for s\n";
- strcpy(s,str);
- }
- my_string::my_string(const my_string&obj)
- {
- s=new char[strlen(obj.s)+1];
- strcpy(s,obj.s);
- cout<<"Copy constructor called.\n";
- }
- void display(my_string ob)
- {
- ob.show();
- }
- int main()
- {
- my_string obj("Hello!");
- display(obj);
- obj.show();
- return 0;
- }
当函数display()结束时候,对象副本被销毁,此时将调用析构函数,析构函数会释放ob.s所指的动态内存空间。不会影响对象obj。
复制构造函数只有在初始化对象的时候才被调用。例如:
- my_string s1("Hello"),s2("world");
- s1=s2;
- 则在上面的代码中:s1=s2执行的是赋值运算,而不是初始化
当使用一个对象来初始化另一个对象的时候,也将调用复制构造函数。
- #include<iostream>
- #include<cstring>
- using namespace std;
- class my_string
- {
- char *s;
- public:
- my_string(char*str);//普通构造函数
- my_string(const my_string&obj);//自定义的复制构造函数
- ~my_string(){
- if(s)
- delete [] s;
- cout<<"Freeing s\n";
- }
- void show()
- {
- cout<<s<<"\n";
- }
- };
- my_string::my_string(char*str)
- {
- s=new char[strlen(str)+1];
- cout<<"Normal constructor called.\n";
- strcpy(s,str);
- }
- my_string::my_string(const my_string&obj)
- {
- s=new char[strlen(obj.s)+1];
- strcpy(s,obj.s);
- cout<<"copy constructor called.\n";
- }
- int main()
- {
- my_string obj("Hello!");//调用构造函数
- my_string ob1(obj);//调用复制构造函数
- my_string ob2=ob1;//调用复制构造函数
- ob1.show();
- ob2.show();
- return 0;
- }
函数创建了一个临时对象保存要返回的值,而函数锁返回的对象实际上是这个临时对象,在对象的值被返回之后,临时对象将被销毁。(在某种情况下会引发不可预料的后果)
例如:
- #include<iostream>
- #include<cstring>
- using namespace std;
- class my_string
- {
- char *s;
- public:
- my_string(char*str);//普通构造函数
- // my_string(const my_string&obj);//自定义的复制构造函数
- ~my_string(){
- if(s)
- delete [] s;
- cout<<"Freeing s\n";
- }
- void show()
- {
- cout<<s<<"\n";
- }
- };
- my_string::my_string(char*str)
- {
- s=new char[strlen(str)+1];
- cout<<"Normal constructor called.\n";
- strcpy(s,str);
- }
- /*
- my_string::my_string(const my_string&obj)
- {
- s=new char[strlen(obj.s)+1];
- strcpy(s,obj.s);
- cout<<"copy constructor called.\n";
- }
- */
- my_string input()//返回一个my_stirng类型的对象
- {
- char instr[80];
- cout<<"Enter a string:";
- cin>>instr;
- my_string ob(instr);//调用普通构造函数
- return ob;
- }
- int main()
- {
- my_string obj=input();//调用默认的复制构造函数
- //在函数input中调用普通的构造函数
- obj.show();
- return 0;
- }
----》避免出现错误的一个方法是返回一个对象指针或者对象引用。
另一种方法就是使用自定义的复制构造函数。
- #include<iostream>
- #include<cstring>
- using namespace std;
- class my_string
- {
- char *s;
- public:
- my_string(char *str);//普通构造函数
- my_string(const my_string &obj);//自定义的复制构造函数
- ~my_string(){
- if(s)
- delete [] s;
- cout<<"Freeing s\n";
- }
- void show()
- {
- cout<<s<<"\n";
- }
- };
- my_string::my_string(char *str)
- {
- s=new char[strlen(str)+1];
- cout<<"Normal constructor called.\n";
- strcpy(s,str);
- }
- my_string::my_string(const my_string &obj)
- {
- s=new char[strlen(obj.s)+1];
- strcpy(s,obj.s);
- cout<<"copy constructor called.\n";
- }
- my_string input()
- {
- char instr[80];
- cout<<"Enter a string:";
- cin>>instr;
- my_string ob(instr);
- return ob;
- }
- int main()
- {
- my_string obj=input();//调用复制构造函数
- //在函数input()中调用普通构造函数
- obj.show();
- return 0;
- }
- 最近笔试总结一
- 最近笔试总结二
- 最近笔试面试总结
- 最近一周笔试面试总结
- Java-最近面试笔试总结
- 最近笔试面试没答全的题目总结
- 笔试总结一
- 最近一段时间总结(一)
- Java笔试题总结(一)
- Java笔试题总结(一) .
- 笔试面试总结(一)
- 多线程笔试面试总结(一)
- 多线程笔试面试总结(一)
- 笔试知识点总结(一)
- C++ prime/笔试 总结一
- 笔试总结篇(一) : 广州X公司笔试
- 最近笔试面试有感
- 最近的笔试面试
- 内存耗用:VSS/RSS/PSS/USS
- java接口实例化问题
- MYSQL数据库备份与恢复
- JSP页面跳转大全
- INSTALL_FAILED_INSUFFICIENT_STORAGE错误解决方法
- 最近笔试总结一
- [JavaScript] dynamic HTML table with JavaScript
- php插件 Simple_HTML_DOM 用DOM方式处理HTML
- 在VC++应用程序中读取文本数据
- php自动加载机制autoload
- error C2664: “MessageBoxW”: 不能将参数 2 从“const char [10]”转换为“LPCWSTR”
- 宏与函数
- asp 在线投票
- android如何引入第三方字体