C++拷贝构造函数(复制构造函数)

合集下载

测验1

测验1

一、单选题1.每个类()构造函数A. 只能有一个B. 只可有私有的C. 可以有多个D. 只可有缺省的2.已知类A中的一个成员函数的说明如下:void Set(A &a);则该函数的参数“A &a”的含义是( )A. 指向A的指针为aB. 将变量a的地址赋给类AC. 类A对象引用a用作函数的形参D. 变量A与a按位与后作函数参数3.假定AB为一个类,则执行AB x;语句时将自动调用该类的( )A. 有参构造函数B. 无参构造函数C. 拷贝构造函数D. 赋值构造函数4.拷贝(复制)构造函数的作用是A. 进行数据类型的转换B. 用对象调用成员函数C. 用对象初始化对象D. 用一般类型的数据初始化对象5.下列关于析构函数的描述中,错误的是( )A. 类中有且仅有一个析构函数B. 析构函数可以有形参C. 析构函数没有函数类型D. 析构函数在对象消失时被自动执行6.下列对类的构造函数和析构函数的描述中,正确的是( )A. 构造函数可以重载,析构函数不能B. 构造函数不能重载,析构函数可以C. 构造函数可以重载,析构函数也可以重载D. 构造函数不能重载,析构函数也不能重载7.假定MyClass为一个类,那么下列的函数说明中,( )为该类的析构函数.A. void ~MyClass();B. ~MyClass(int n);C. MyClass();D. ~MyClass();8.为了使类中的成员不能被类的对象通过成员操作符访问,则不能把该成员的访问权限定义为A. publicB. protectedC. privateD. static9.下列对与拷贝构造函数的描述中,正确的( )A. 在C++中,如果不自定义类的拷贝构造函数,则每个类都有默认的拷贝构造函数B. 必须为每个类定义拷贝初始化构造函数C. 如果要使用拷贝构造函数,则必须在类中显示进行定义D. 定义拷贝构造函数则无须定义构造函数10.对于下面定义的类MyClass,在函数f()中将对象成员n的值修改为50的语句(划线处)应该是( )class MyClass{public:MyClass(int x){n=x;}void SetValue(int n1){n=n1;}private:int n;};int f(){MyClass *ptr=new MyClass(45);__________;}A. MyClass(50)B. SetValue(50)C. ptr - > SetValue(50)D. ptr - > n=50二、填空题1. ______运算符对指定类型对象动态分配内存并返回该类型的指针。

详解C++中构造函数,拷贝构造函数和赋值函数的区别和实现

详解C++中构造函数,拷贝构造函数和赋值函数的区别和实现

详解C++中构造函数,拷贝构造函数和赋值函数的区别和实现C++中⼀般创建对象,拷贝或赋值的⽅式有构造函数,拷贝构造函数,赋值函数这三种⽅法。

下⾯就详细⽐较下三者之间的区别以及它们的具体实现1.构造函数构造函数是⼀种特殊的类成员函数,是当创建⼀个类的对象时,它被调⽤来对类的数据成员进⾏初始化和分配内存。

(构造函数的命名必须和类名完全相同)⾸先说⼀下⼀个C++的空类,编译器会加⼊哪些默认的成员函数默认构造函数和拷贝构造函数析构函数赋值函数(赋值运算符)取值函数**即使程序没定义任何成员,编译器也会插⼊以上的函数!注意:构造函数可以被重载,可以多个,可以带参数;析构函数只有⼀个,不能被重载,不带参数⽽默认构造函数没有参数,它什么也不做。

当没有重载⽆参构造函数时,A a就是通过默认构造函数来创建⼀个对象下⾯代码为构造函数重载的实现<span style="font-size:14px;">class A{int m_i;Public:A(){Cout<<”⽆参构造函数”<<endl;}A(int i):m_i(i) {} //初始化列表}</span>2.拷贝构造函数拷贝构造函数是C++独有的,它是⼀种特殊的构造函数,⽤基于同⼀类的⼀个对象构造和初始化另⼀个对象。

当没有重载拷贝构造函数时,通过默认拷贝构造函数来创建⼀个对象A a;A b(a);A b=a; 都是拷贝构造函数来创建对象b强调:这⾥b对象是不存在的,是⽤a 对象来构造和初始化b的!!先说下什么时候拷贝构造函数会被调⽤:在C++中,3种对象需要复制,此时拷贝构造函数会被调⽤1. 1)⼀个对象以值传递的⽅式传⼊函数体2. 2)⼀个对象以值传递的⽅式从函数返回3. 3)⼀个对象需要通过另⼀个对象进⾏初始化什么时候编译器会⽣成默认的拷贝构造函数:1. 1)如果⽤户没有⾃定义拷贝构造函数,并且在代码中使⽤到了拷贝构造函数,编译器就会⽣成默认的拷贝构造函数。

(完整版)拷贝构造函数

(完整版)拷贝构造函数
}
};
//全局函数
CExample g_Fun()
{
CExample temp(0);
return temp;
}
int main()
{
g_Fun();
return 0;
}
当g_Fun()函数执行到return时,会产生以下几个重要步骤:
(1). 先会产生一个临时变量,就叫XXXX吧。
(2). 然后调用拷贝构造函数把temp的值给XXXX。整个这两个步骤有点像:CExample XXXX(temp);(3). 在函数执行到最后先析构temp局部变量。
class CExample {
private:
int a;
public:
//构造函数
CExample(int b)
{ a = b;}
//拷贝构造函数
CExample(const CExample& C)
{
a = C.a;
}
//一般函数
void Show ()
{
cout<<a<<endl;
}
};
int main()
a = C.a;
cout<<"copy"<<endl;
}
//析构函数
~CExample()
{
cout<< "delete: "<<a<<endl;
}
void Show ()
{
cout<<a<<endl;
}
};
//全局函数,传入的是对象
void g_Fun(CExample C)

c++ string类的常用方法

c++ string类的常用方法

c++ string类的常用方法一、C++ string类的常用方法1、string类的构造函数string() // 构造空串string(const char* s) // 把null结尾的字符串s拷贝到字符串中string(const string& str) // 拷贝构造函数,复制str到此串string(char c, int n) // 用n个字符c构造串string(const char* s, int n) // 拷贝字符数组中前n个字符2、string类的成员函数2.1 长度控制函数int size() const; // 返回字符串的长度int length() const; // 返回字符串的长度,等价于size()void resize(int n, char c); // 改变字符串长度,如果n 大于原来的长度,用字符c来填充2.2 内容操作函数string& operator=(const char* s); // 赋值,把s的内容复制到字符串中string& assign(const char* s); // 赋值,把s的内容复制到字符串中string& append(const char* s); // 把字符串s添加到串尾string& append(const char* s, int n); // 把s前n个字符添加到串尾string& insert(int p0, const char* s); // 在p0位置上插入字符串sstring& erase(int p0, int n); // 删除p0开始,n个字符int find(const char* s, int pos=0); // 在pos之后查找子串s,返回子串s在原串中的起始位置int find(char c, int pos=0); // 从pos开始查找字符c,返回字符c在原串中的位置int rfind(const char* substr,int pos=npos); // 从pos开始向前查找子串substr,返回子串substr在原串中的起始位置int rfind(char c, int pos=npos); // 从pos开始向前查找字符c,返回字符c在原串中的位置string substr(int pos, int n); // 返回串pos 位置开始,长度为n的子串2.3 字符串比较函数int compare(const char* s); // 比较原串和sint compare(int p0, int n, const char* s); // 比较串中p0开始,n个字符的子串和s2.4 数据访问函数char& operator[](int i); // 返回串中第i个字符的引用const char& operator[](int i) const; // 返回串中第i个字符的引用const char* c_str() const; // 返回字符串以null结尾的字符串2.5 输入输出函数ostream& operator<<(ostream& os, const string& str); // 输出字符串istream& operator>>(istream& is, string& str); // 输入字符串。

C++拷贝(复制)构造函数详解

C++拷贝(复制)构造函数详解

C++拷贝(复制)构造函数详解⼀. 什么是拷贝构造函数⾸先对于普通类型的对象来说,它们之间的复制是很简单的,例如:[c-sharp]1. int a = 100;2. int b = a;⽽类对象与普通对象不同,类对象内部结构⼀般较为复杂,存在各种成员变量。

下⾯看⼀个类对象拷贝的简单例⼦。

[c-sharp]1. #include <iostream>2. using namespace std;3.4. class CExample {5. private:6. int a;7. public:8. //构造函数9. CExample(int b)10. { a = b;}11.12. //⼀般函数13. void Show ()14. {15. cout<<a<<endl;16. }17. };18.19. int main()20. {21. CExample A(100);22. CExample B = A; //注意这⾥的对象初始化要调⽤拷贝构造函数,⽽⾮赋值23. B.Show ();24. return 0;25. }运⾏程序,屏幕输出100。

从以上代码的运⾏结果可以看出,系统为对象 B 分配了内存并完成了与对象 A 的复制过程。

就类对象⽽⾔,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。

下⾯举例说明拷贝构造函数的⼯作过程。

[c-sharp]1. #include <iostream>2. using namespace std;3.4. class CExample {5. private:6. int a;7. public:8. //构造函数9. CExample(int b)10. { a = b;}11.12. //拷贝构造函数13. CExample(const CExample& C)14. {15. a = C.a;16. }17.18. //⼀般函数19. void Show ()20. {21. cout<<a<<endl;22. }23. };24.25. int main()26. {27. CExample A(100);28. CExample B = A; // CExample B(A); 也是⼀样的29. B.Show ();30. return 0;31. }CExample(const CExample& C) 就是我们⾃定义的拷贝构造函数。

西安交通大学3月课程考试《面向对象程序设计(高起专)》作业考核试题

西安交通大学3月课程考试《面向对象程序设计(高起专)》作业考核试题
正确答案:D
31:不能通过派生类对象引用从私有基类继承过来的任何成员。( )
A:错误
B:正确
正确答案:B
32:对使用默认参数的构造函数,如果在类外定义构造函数,应该在定义构造函数时指定默认值( )。
A:错误
B:正确
正确答案:A
33:如果定义了一个类的对象数组,该数组有10个元素,则要调用10次构造函数来对每个元素初始化。( )。
A:错误
B:正确
正确答案:A
49:在用class定义一个类时,如果不加声明,数据成员和成员函数默认的访问权限是public。( )
A:错误
B:正确
正确答案:A
50:友元类必须被说明为公用成员。( 案:A
D:20和5
正确答案:C
15:关于运行时多态的下列描述中,()是错误的。
A:运行时多态是以虚函数为基础的;
B:运行时多态是在运行时确定所调用的函数代码的;
C:用基类指针或引用所标识的派生类对象来操作虚函数才能实现运行时多态;
D:运行时多态是在编译时确定操作函数的。
正确答案:D
16:下面是五条顺序出现的声明语句,非法的初始化语句是()。
B:x [a]
C:x-&gt;a
D:x.a
正确答案:D
5:继承机制的作用是( )。
A:信息隐藏
B:数据封装
C:定义新类
D:数据抽象
正确答案:C
6:面向对象软件开发中使用的OOD表示( )。
A:面向对象分析
B:面向对象设计
C:面向对象语言
D:面向对象方法
正确答案:B

结构体拷贝构造函数

结构体拷贝构造函数

结构体拷贝构造函数
结构体是C语言中一种很常用的数据类型,它可以将不同类型的数据组合在一起,为使用者提供了很多方便。

对于结构体,有时当我们想要复制一个结构体时,就需要用到结构体拷贝构造函数,它可以将一个已经存在的结构体拷贝到新结构体中。

原来的结构体在构造函数中传入,该构造函数实现的功能是使用原始结构体的信息来构造一个新的结构体。

构造函数一般有两种,一种是深拷贝(deep copy),其中,拷贝函数会完全复制原来结构体里面的每个成员;另一种是浅拷贝(shallow copy),只会复制原来结构体里面的指针类型成员,而不会拷贝里面的值,也就是说,新的结构体里的指针类型成员,都指向原来的结构体里的成员。

对于深拷贝而言,不仅会拷贝结构体本身里面的成员,还会拷贝指针类型的成员;而对于浅拷贝,只会拷贝原来结构体里面的指针类型成员,指向的内容还是原来的结构体里的内容,而不会再开辟新的内存空间。

总之,结构体拷贝构造函数可以将一个已有的结构体拷贝到一个新的结构体中,数据会以浅拷贝或者深拷贝的方式进行复制,让用户更方便地实现数据复制。

c++中拷贝构造函数,浅拷贝和深拷贝的区别,以及移动构造函数总结

c++中拷贝构造函数,浅拷贝和深拷贝的区别,以及移动构造函数总结

c++中拷贝构造函数,浅拷贝和深拷贝的区别,以及移动构造函数总结⼀、构造函数、浅拷贝和深拷贝在C++提供了⼀种特殊的构造函数,称为拷贝构造函数。

拷贝构造函数具有⼀般构造函数的所有特性,其作⽤是使⽤⼀个已经存在的对象(由拷贝构造函数的参数指定的对象)去初始化⼀个新的同类对象,即完成本类对象的复制。

程序员如果没有定义拷贝构造函数,系统会⾃动⽣成⼀个默认的拷贝构造函数,其功能是把已存在的每个数据成员都复制到新对象中。

程序员定义拷贝构造函数时,⼀般形式: 类名(类名 & 对象){}拷贝构造函数在三种情况下会被⾃动调⽤(1)⽤⼀个对象去初始化⼀个同类的对象 XX B(A) (2) XX aa = a,当⼀个新对象被定义的时候,即便这个时候是使⽤了'='运算符,它真实调⽤的是初始化函数copy constructor,⽽不是调⽤copy assignment operator去进⾏赋值操作。

;(3)如果函数的形参是对象,进⾏形参和实参结合时,调⽤拷贝构造函数。

f(A);(4)如果函数的返回值是对象,返回主调函数时,调⽤拷贝构造函数。

XX B=g();其中默认的拷贝构造函数是浅拷贝。

当类的数据成员有指针类型是,假设同类对象A初始化B,A和B对象使⽤同⼀内存区域。

在撤销对象时,导致对这⼀内存的两次释放,也就是说浅层复制:只复制指向对象的指针,⽽不复制引⽤对象本⾝。

这时候要求程序员编制拷贝构造函数,使对象B的指针指向另外的内存区域,这叫深拷贝,深层复制:复制引⽤对象本⾝。

⼆、移动构造函数右值引⽤,临时值,如果是临时值,不调⽤深拷贝,⽽是移动构造函数(move construct),来提升性能。

#include<iostream>using namespace std;class Test{public:Test() :x(0){cout << "构造函数 this = " << this << endl;}Test(int x) :x(x){cout << "构造函数 this = " << this << endl;}Test(const Test& another) :x(another.x){cout << "拷贝构造函数 this = " << this << " from " << &another << endl;}Test(const Test&& another) : x(another.x){cout << "移动构造函数 this = " << this<< " from " << &another << endl;}~Test(){cout << "析构函数 this = " << this << endl;}friend ostream& operator<<(ostream& out, const Test &t);private:int x;};//运算符重载ostream& operator<<(ostream& out, const Test &t){out << "&t = " << &t << ",x = " << t.x;return out;}Test maketest(){Test x(4);cout << "hell" << endl;return x;}int main(){//测试拷贝构造函数Test test(3);cout << test << endl;Test test2(test);cout << test2 << endl;cout << endl;//测试移动构造函数Test first = maketest();//有⼀个临时对象,cout << first << endl;cout << endl;system("pause");}//测试移动构造函数1Test first = maketest();//有⼀个临时对象,/*测试1结果分析:正常情况下直接调⽤拷贝构造函数,如果定义了移动构造函数,则直接调⽤移动构造函数。

C++中构造函数作用

C++中构造函数作用

C++中构造函数作⽤⼀、 构造函数是⼲什么的该类对象被创建时,编译系统对象分配内存空间,并⾃动调⽤该构造函数->由构造函数完成成员的初始化⼯作eg: Counter c1;编译系统为对象c1的每个数据成员(m_value)分配内存空间,并调⽤构造函数Counter( )⾃动地初始化对象c1的m_value值设置为0故:构造函数的作⽤:初始化对象的数据成员。

⼆、 构造函数的种类class Complex{private :double m_real;double m_imag;public:// ⽆参数构造函数// 如果创建⼀个类你没有写任何构造函数,则系统会⾃动⽣成默认的⽆参构造函数,函数为空,什么都不做// 只要你写了⼀个下⾯的某⼀种构造函数,系统就不会再⾃动⽣成这样⼀个默认的构造函数,如果希望有⼀个这样的⽆参构造函数,则需要⾃⼰显⽰地写出来Complex(void){m_real = 0.0;m_imag = 0.0;}// ⼀般构造函数(也称重载构造函数)// ⼀般构造函数可以有各种参数形式,⼀个类可以有多个⼀般构造函数,前提是参数的个数或者类型不同(基于c++的重载函数原理)// 例如:你还可以写⼀个 Complex( int num)的构造函数出来// 创建对象时根据传⼊的参数不同调⽤不同的构造函数Complex(double real, double imag){m_real = real;m_imag = imag;}// 复制构造函数(也称为拷贝构造函数)// 复制构造函数参数为类对象本⾝的引⽤,⽤于根据⼀个已存在的对象复制出⼀个新的该类的对象,⼀般在函数中会将已存在对象的数据成员的值复制⼀份到新创建的对象中 // 若没有显⽰的写复制构造函数,则系统会默认创建⼀个复制构造函数,但当类中有指针成员时,由系统默认创建该复制构造函数会存在风险,具体原因请查询 有关 “浅拷贝” 、“深拷贝”的⽂章论述Complex(const Complex & c){// 将对象c中的数据成员值复制过来m_real = c.m_real;m_imag = c.m_imag;}// 类型转换构造函数,根据⼀个指定的类型的对象创建⼀个本类的对象,//需要注意的⼀点是,这个其实就是⼀般的构造函数,但是对于出现这种单参数的构造函数,C++会默认将参数对应的类型转换为该类类型,有时候这种隐私的转换是我们所不想要的,所以需要使⽤explicit来限制这种转换。

复制构造函数和拷贝构造函数

复制构造函数和拷贝构造函数

复制构造函数和拷贝构造函数
复制构造函数和拷贝构造函数是C++中两个重要的概念。

其中,复制构造函数指的是当一个对象被复制到另一个对象时,所调用的构造函数;而拷贝构造函数则是一个特定类型的构造函数,用于从一个已有的对象创建一个新的对象。

重要的是要理解这两个概念之间的区别。

复制构造函数是一个特殊的构造函数,用于创建一个新的对象,而拷贝构造函数则是从一个已存在的对象创建一个新的对象。

这两个函数的实现方式也有所不同,尽管它们的目的都是为了创建一个新的对象。

在C++中,有两种方式可以定义一个拷贝构造函数。

一个是使用一个已有的对象来创建一个新的对象;另一个是使用一个函数来创建一个新的对象。

无论哪种方式,拷贝构造函数的目的都是为了创建一个新的对象,以便可以对其进行操作。

在实际的程序设计中,拷贝构造函数和复制构造函数通常是必须的。

这是因为,如果没有这些函数,程序将无法正确地创建和操作对象。

因此,当编写C++程序时,需要注意这两个概念的区别,并确保正确地实现拷贝构造函数和复制构造函数。

- 1 -。

堆与拷贝构造函数PPT课件

堆与拷贝构造函数PPT课件

new根据参数匹配的原则来调用构造函数,如果写成pD=new Tdate; 则由于TDate类没有提供无参的构造函数而出错。
2021/3/9
6
4.3 分配堆对象
从堆中还可以分配对象数组
class Student {
public: Student(char * pName=“no name”) {
拷贝构造函数是一种特殊的构造函数,具有一般构造 函数的特点,其作用是用一个已经存在的对象去初始 化一个新的同类对象。
2021/3/9
8
4.4 拷贝构造函数
可以根据实际问题的需要定义拷贝构造函数,以实现 同类对象之间数据成员的传递。如果没有自定义类的 拷贝构造函数,系统会自动生成一个默认的拷贝构造 函数,其工作方式是按成员初始化(memberwise initialization),即通过依次拷贝每个非静态数据成 员实现,如果成员是类对象,则调用其拷贝构造函数 或者默认拷贝构造函数。
构造函数被调用num次,依次构造pS[0]到pS[num-1]。
从堆上分配对象数组,只能调用默认构造函数,不能调用任何其他构 造函数。
2021/3/9
7
4.4 拷贝构造函数
如果希望生成一个对象的副本,可以创建一个新的对 象,并将现有对象的数据成员值赋值给新对象的相应 成员。这种方法可行,但繁琐。更好的途径是使类具 有某种复制本类对象的能力,这便是拷贝构造函数 (Copy Constructor)的功能。
strncpy(name,pName,sizeof(name)); name[sizeof(name)-1]=‘\0’; } private: char name[40]; };
void fn(int num) {

C++中拷贝构造函数和赋值运算符函数的比较研究

C++中拷贝构造函数和赋值运算符函数的比较研究




21 0 0年第 4期
C+ + 中拷贝构造 函数和赋值运算符 函数 的 比较研究
冯洪玉 ,梁云娟
(河 南科 技 学 院信 息工 程 学 院 河 南 新 乡 4 30 5 0 3)
【 摘
要】 :本 文首先探 讨 了浅拷 贝和 深拷 贝问题 , 明定义拷 贝构造 函数和赋值 运算符 函数 的必要性 , 次对二 者从 说 其
图 I默 认 拷 贝 构造 函数 执 行 示 意 图

p v t: i r ae
c a s N me hr u a ; r
p b i: ul c
C esn h s Pr ( a 1 o cr

我 们 再 以图 2为 例 。看一 下 默 认 的赋 值 运 算 符 函数 实 现 的 功 能 。 图 2可 以 看 出 , 里 同 样 只是 将 对象 fu 中 字符 指 针 的 从 这 or 首 地 址 简单 赋 值 给 了对 象 tre的 指 针 成 员 .造 成 对 象 f r he o 和 u tre 同 使 用 同 一块 内存 空 间 存 放 字 符 数 组 . 以也 出 现 了 上 he 共 所 述 的 运行 结 果 。 上 述两 种 赋 值 方 式 都 是 仅 仅 将 对 象 的 数 据成 员 进 行 了 对应 的拷 贝 。 这种 拷 贝 方 式称 为浅 拷 贝 。
动 态 空间
sNm =e asl (+] r u a e n wc r te s 1 h [rn ) ; sc y t a e ) t p( r m ,; r sN s



动 态 空 闻
C eo0 Pr n s

isra e fu m ) (N

原型模式和C++的拷贝构造函数有什么区别

原型模式和C++的拷贝构造函数有什么区别

原型模式和C++的拷贝构造函数有什么区别
都是基于个⼈理解,本⽂是为了帮助记忆。

相同点:原型模式和拷贝构造函数都是要产⽣对象的复制品。

不同点:原型模式实现的是⼀个clone接⼝,注意是接⼝,也就是基于多态的clone虚函数。

也就是说原型模式能够通过基类指针来复制派⽣类对象。

拷贝构造函数完不成这样的任务。

原型模式的核⼼是克隆,构造函数只是克隆的⼀个办法⽽已。

class base
{
public :
base();
base(base &obj);
virtual ~base();
virtual base *clone() { return new base(*this) ; };
};
class derived : public base
{
public :
derived();
derived( derived &);
virtual base *clone(){return new derived (*this); }
....
};
base *obj1 = new base ;
base *obj2 = new derived ;
base *obj3 = obj1 .clone();
base *obj4 = obj12.clone();。

几种基本构造函数

几种基本构造函数

几种基本构造函数随着现代编程语言的发展,构造函数的应用越来越广泛,成为面向对象编程中不可少的一环。

构造函数是一种用来创建对象的函数,用于将状态赋值给对象,以便在程序中进行操作。

本文将介绍几种基本的构造函数。

1. 默认构造函数默认构造函数是C++中最基本的构造函数之一。

当对象没有显式的构造函数时,编译器会调用默认构造函数。

默认构造函数也是最简单的构造函数之一,它不带任何参数,仅负责对类的成员变量进行初始化,通常赋初值为0或者空值。

例如:```c++ class Person{ public:Person(){ height = 0; weight =0; } private: int height; intweight; }; ```2. 带参数构造函数带参数构造函数在声明时需要传递参数,用于在创建对象的同时对成员变量进行赋值。

参数个数以及类型根据实际应用可变,可以是基本数据类型、对象或指针等。

例如:```c++ class Person{ public: Person(int h, int w){ height = h; weight =w; } private: int height; intweight; }; ``` 在使用带参数构造函数创建对象时,需要传入相应的参数:```c++ Person person1(170, 60); ```这样person1的height属性就被初始化为170,weight属性被初始化为60。

3. 拷贝构造函数拷贝构造函数主要用于对象之间的赋值,它的参数是一个对象的引用。

当使用一个对象初始化另一个对象时,拷贝构造函数会被调用。

例如:```c++ class Person{ public: Person(const Person& p){ height = p.height;weight = p.weight; } private: int height; int weight; }; ```拷贝构造函数的参数声明中使用了const关键字,这是为了保证传递的参数不被修改。

c++ string的构造函数

c++ string的构造函数

c++ string的构造函数C++中的string类提供了多种构造函数,用于创建字符串对象并进行初始化。

这些构造函数可以接受不同的参数类型,以便根据需要创建字符串。

1. 默认构造函数:string类的默认构造函数创建一个空字符串对象,没有任何字符。

示例:```cppstring s; // 创建一个空字符串对象```2. 字符串字面值构造函数:string类还提供了从C风格字符串(字符串字面值)创建字符串对象的构造函数。

这个构造函数将字符串字面值作为参数,并将其复制到新创建的字符串对象中。

示例:```cppstring s('Hello World'); // 从字符串字面值创建字符串对象 ```3. 重复字符构造函数:这个构造函数接受一个字符和一个整数作为参数,用于创建一个由指定数量的重复字符组成的字符串对象。

示例:```cppstring s(5, 'a'); // 创建一个由5个重复的字符'a'组成的字符串对象```4. 拷贝构造函数:拷贝构造函数用于创建一个新的字符串对象,并将另一个字符串对象的内容复制到新对象中。

示例:```cppstring s1('Hello');string s2(s1); // 使用拷贝构造函数创建一个新的字符串对象,并将s1的内容复制到s2中```这些是string类的一些常用构造函数,它们可以根据不同的需求创建字符串对象并进行初始化。

除了这些构造函数之外,string类还提供了其他一些构造函数,如从字符指针、迭代器范围等创建字符串对象的构造函数。

通过选择适当的构造函数,我们可以方便地创建并初始化字符串对象。

c++中的拷贝构造函数

c++中的拷贝构造函数

c++中的拷贝构造函数1拷贝构造函数的作用和定义拷贝构造函数是C++中一个重要的概念,它的作用是在已有对象的基础上创建一个新的对象。

具体来说,拷贝构造函数可以将一个对象中的数据成员值复制到另一个对象中,从而使得新的对象与旧的对象具有相同的数据。

在C++中,拷贝构造函数的函数名是固定的,即它的函数名必须与类名相同,参数是一个指向const的类类型引用,即:```Classname(const Classname&obj);```其中,Classname表示类名,obj表示要拷贝的对象。

2拷贝构造函数的默认实现如果一个类没有提供自己的拷贝构造函数,C++编译器将会为它生成一个默认的拷贝构造函数,该拷贝构造函数执行浅拷贝操作,即只是将对象的成员变量逐个拷贝给新的对象,并不会为新的对象重新分配内存。

例如,下面是一个简单的例子:```include<iostream>using namespace std;class MyClass{public:MyClass(int x){mX=x;}void printX()const{cout<<mX<<endl;} private:int mX;};int main(){MyClass obj1(100);MyClass obj2=obj1;obj1.printX();//输出:100obj2.printX();//输出:100return0;}```在这个例子中,MyClass类没有提供自己的拷贝构造函数,因此编译器会为它生成一个默认的拷贝构造函数。

在执行`MyClass obj2= obj1;`语句时,obj2将会被初始化为obj1的一个拷贝,即它们的数据成员都是相同的。

因此,obj2和obj1的printX()函数输出的结果都是100。

需要注意的是,在默认实现的拷贝构造函数中,如果类中含有指针等动态分配内存的成员变量,拷贝的结果可能是不正确的。

第14章堆与拷贝构造函数

第14章堆与拷贝构造函数

Constructing new student Randy Calling fn() Constructing copy of Randy In function fn() Destructing copy of Randy Return from fn() Destructing Randy
默认拷贝构造函数
14.2不能使用malloc()和free()原因
类对象的建立是分配空间、构造结构以及初始化的三位一体,它们 统一由构造函数来完成。
14.3 分配堆对象
C++的new和delete机制更简单易懂。 void fn() { Tdate* pS; pS=new Tdate; //分配堆空间并构造它 //... delete ps; //先析构,然后将空间返还给堆 }
类定义中,如果未提供自己的拷贝构造函数, 则C++ 提供一个默认拷贝构造函数。 C++提供的默认拷贝构造函数工作的方法是, 完 成一个成员一个成员的拷贝。如果成员是类对象, 则调用其拷贝构造函数或者默认拷贝构造函数。
例 14-2
默认拷贝构造函数的使用
#include <iostream.h> #include <string.h> class Student{ public: Student(char* pName="no name") { cout <<"Constructing new student " <<pName <<endl; strncpy(name,pName,sizeof(name)); name[sizeof(name)-1]='\0'; }

[笔记]C++拷贝构造和移动构造

[笔记]C++拷贝构造和移动构造

[笔记]C++拷贝构造和移动构造⼀、拷贝构造 如果⼀个构造函数的第⼀个参数是⾃⾝类类型的引⽤,且任何额外参数都没有默认值,则此构造函数是拷贝构造函数。

(《C++Primer,第五版》)class Foo{public :Foo();Foo(const Foo&); //拷贝构造函数Foo& operator=(const Foo&); //拷贝赋值运算符}; 类的成员中有指针时,使⽤深拷贝。

#include <iostream>using namespace std;class Foo{public:Foo(){pInt = new int;*pInt = 1;}Foo(const Foo&)= default; //拷贝构造函数Foo& operator=(const Foo&) = default; //拷贝赋值运算符int* pInt;};//浅拷贝,foo1和foo2中的pInt指向同⼀块内存地址Foo foo1;Foo foo2(foo1);//深拷贝class Cop{public:Cop(){pInt = new int;*pInt = 2;}Cop(const Cop& cop){pInt = new int;*pInt = *(cop.pInt);}int* pInt;};//深拷贝,cop1和cop2中pInt指向不同内存Cop cop1;Cop cop2(cop1);⼆、移动构造 在某些情况下(函数返回对象引⽤),对象拷贝后⽴即就被消耗了。

拷贝构造就回造成性能上的浪费,⽽且深拷贝也会造成浪费。

移动构造可以避免这种情况的发⽣。

为了⽀持移动构造,C++11引⼊了右值引⽤。

右值引⽤:必须绑定到右值的引⽤,通过&&来获得右值引⽤,类似左值引⽤(常规引⽤),右值应⽤也是⼀块内存的别名。

右值:字⾯常量、在表达式求值过程中临时创建的对象,这些使⽤过后就被销毁的资源。

c++ 赋值构造函数

c++ 赋值构造函数

c++ 赋值构造函数构造函数主要包括:默认构造函数、普通构造函数、拷贝构造函数三种。

构造函数经常与赋值函数混淆,这里放在一起讲,便于区分。

首先初始化一个简单的类作为例子讲解:classA{public:A(){v =1;printf("默认构造(无参数)\n");}A(int t=1){v =1;printf("默认构造(有参数,且参数有默认值)\n");}A(int t){v = t;printf("普通构造1\n");}A(int t,int f){v = t;m = f;printf("普通构造2\n");}A(const A&a){this->v = a.v;printf("拷贝构造\n");}A&operator=( A& a){this->v = a.v;printf("赋值函数\n");return*this;}~A(){printf("析构函数\n");}int v;int m;};1、默认构造函数①准确的说,默认构造函数就是在调用时不需要显示地传入实参的构造函数。

②一个类只能有一个默认构造函数。

1.1、默认构造函数当类中没有定义任何构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空。

此外,用户可自定义默认构造函数如下。

实现形式:A(){}A(int t =1){v = t;}上述两种默认构造函数不能同时存在,否则在调用默认构造函数时会引起二义性。

调用形式:intmain(){A a;return0;}*C++构造函数重载以及默认参数引起的二义性问题解析当我们同时定义一个带默认参数的默认构造函数和一个不带参数的默认构造函数之后(一般不这样做,两种构造函数不应被同时定义),在定义一个类对象时,如果不传递参数,会出现二义性错误。

构造函数 虚函数

构造函数 虚函数

构造函数虚函数1.构造函数构造函数是一种特殊的函数,用于创建对象时执行必要的初始化任务。

每个类只能有一个构造函数,并且与类同名。

构造函数不能有返回类型,即使是void也不行;并且不能被声明为const、volatile或const volatile。

以下是一些常见的构造函数类型:默认构造函数:无参构造函数,当创建对象时没有提供参数时即被调用。

拷贝构造函数:接受const&类型的引用参数,用于创建新对象并将旧对象的数据复制到新对象中。

带参构造函数:接受一个或多个参数,用于在创建对象时进行初始化。

析构函数是与构造函数相对应的,用于对象销毁前执行必要的清理任务。

析构函数与构造函数一样只有一个,并且没有返回类型。

2.虚函数虚函数是在运行时动态绑定,即通过基类指针或引用调用时会根据实际指向的对象的类型来调用相应的派生类函数的一种函数。

通过将基类成员函数声明为虚函数,可以实现多态性,使得基类指针或引用可以指向任意派生类对象。

以下是虚函数的一些特点:虚函数的函数名前面要加上virtual关键字,作为函数声明的一部分。

虚函数可以有实现,也可以没有,如果没有实现,则称为纯虚函数,需要在基类中声明为纯虚函数,即在函数后面加上=0,派生类必须重写该函数。

虚函数必须是非静态成员函数,不能是全局函数,也不能是静态成员函数。

虚函数的使用必须通过基类的指针或引用进行调用,不能直接调用。

派生类中重写基类的虚函数时,函数签名(函数名、参数列表、返回类型)必须与基类的虚函数相同,可见性可以更宽。

3.中文中文是不同于拉丁字母的表音文字系统,使用口音来对应一系列符号。

中文是全球使用最广泛的文字之一,被认为是人类文明中的重要发明之一。

中文分为繁体字和简体字两种形式,繁体字主要在香港、台湾等地使用,而简体字则是中国大陆通用。

现在,许多程序界面和文档被翻译成了中文,在程序设计和开发方面,学习中文也是很有用的一项技能。

总结构造函数和虚函数是C++中很重要的两个概念。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

有的、已经存在的数据创建出一份新的数据,最终的结果是多了一份相同的数据。

例如,将Word 文档拷贝到U盘去复印店打印,将D 盘的图片拷贝到桌面以方便浏览,将重要的文件上传到百度网盘以防止丢失等,都是「创建一份新数据」的意思。

在C++ 中,拷贝并没有脱离它本来的含义,只是将这个含义进行了“特化”,是指用已经存在的对象创建出一个新的对象。

从本质上讲,对象也是一份数据,因为它会占用内存。

严格来说,对象的创建包括两个阶段,首先要分配内存空间,然后再进行初始化:
∙分配内存很好理解,就是在堆区、栈区或者全局数据区留出足够多的字节。

这个时候的内存还比较“原始”,没有被“教化”,它所包含的数据一般是零值或者随机值,没有实际的意义。

∙初始化就是首次对内存赋值,让它的数据有意义。

注意是首次赋值,再次赋值不叫初始化。

初始化的时候还可以为对象分配其他的资源(打开文件、连接网络、动态分配内存等),或者提前进行一些计算(根据价格和数量计算出总价、根据长度和宽度计算出矩形的面积等)等。

说白了,初始化就是调用构造函数。

很明显,这里所说的拷贝是在初始化阶段进行的,也就是用其它对象的数据来初始化新对象的内存。

那么,如何用拷贝的方式来初始化一个对象呢?其实这样的例子比比皆是,string 类就是一个典型的例子。

1.#include<iostream>
2.#include<string>
ing namespace std;
4.
5.void func(string str){
6.cout<<str<<endl;
7.}
8.
9.int main(){
10.string s1 ="";
11.string s2(s1);
12.string s3 = s1;
13.string s4 = s1 +" "+ s2;
14.func(s1);
15.cout<<s1<<endl<<s2<<endl<<s3<<endl<<s4<<endl;
16.
17.return0;
18.}
运行结果:

s1、s2、s3、s4 以及func() 的形参str,都是使用拷贝的方式来初始化的。

对于s1,表面上看起来是将一个字符串直接赋值给了s1,实际上在内部
进行了类型转换,将const char * 类型转换为string 类型后才赋值的,
这点我们将在《C++转换构造函数》一节中详细讲解。

s4 也是类似的道
理。

对于s1、s2、s3、s4,都是将其它对象的数据拷贝给当前对象,以完成当前对象的初始化。

对于func() 的形参str,其实在定义时就为它分配了内存,但是此时并没有初始化,只有等到调用func() 时,才会将其它对象的数据拷贝给str 以完成初始化。

当以拷贝的方式初始化一个对象时,会调用一个特殊的构造函数,就是拷贝构造函数(Copy Constructor)。

下面的例子演示了拷贝构造函数的定义和使用:
1.#include<iostream>
2.#include<string>
ing namespace std;
4.
5.class Student{
6.public:
7.Student(string name ="",int age =0,float score =0.0f);//普通构造函数
8.Student(const Student &stu);//拷贝构造函数(声明)
9.public:
10.void display();
11.private:
12.string m_name;
13.int m_age;
14.float m_score;
15.};
16.
17.Student::Student(string name,int age,float score):m_name(name),m_age(age),
m_score(score){}
18.
19.//拷贝构造函数(定义)
20.Student::Student(const Student &stu){
21.this->m_name = stu.m_name;
22.this->m_age = stu.m_age;
23.this->m_score = stu.m_score;
24.
25.cout<<"Copy constructor was called."<<endl;
26.}
27.
28.void Student::display(){
29.cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
30.}
31.
32.int main(){
33.Student stu1("小明",16,90.5);
34.Student stu2 = stu1;//调用拷贝构造函数
35.Student stu3(stu1);//调用拷贝构造函数
36.stu1.display();
37.stu2.display();
38.stu3.display();
39.
40.return0;
41.}
运行结果:
Copy constructor was called.
Copy constructor was called.
小明的年龄是16,成绩是90.5
小明的年龄是16,成绩是90.5
小明的年龄是16,成绩是90.5
第8 行是拷贝构造函数的声明,第20 行是拷贝构造函数的定义。

拷贝构造函数只有一个参数,它的类型是当前类的引用,而且一般都是const 引用。

1) 为什么必须是当前类的引用呢?
如果拷贝构造函数的参数不是当前类的引用,而是当前类的对象,那么在调用拷贝构造函数时,会将另外一个对象直接传递给形参,这本身就是一次拷贝,会再次调用拷贝构造函数,然后又将一个对象直接传递给了形参,将继续调用拷贝构造函数……这个过程会一直持续下去,没有尽头,陷入死循环。

只有当参数是当前类的引用时,才不会导致再次调用拷贝构造函数,这不仅是逻辑上的要求,也是C++ 语法的要求。

2) 为什么是const 引用呢?
拷贝构造函数的目的是用其它对象的数据来初始化当前对象,并没有期望更改其它对象的数据,添加const 限制后,这个含义更加明确了。

另外一个原因是,添加const 限制后,可以将const 对象和非const 对象传递给形参了,因为非const 类型可以转换为const 类型。

如果没有const 限制,就不能将const 对象传递给形参,因为const 类型不能转换为非const 类型,这就意味着,不能使用const
对象来初始化当前对象了。

以上面的Student 类为例,将const 去掉后,拷贝构造函数的原型变为:
此时,下面的代码就会发生错误:
1.const Student stu1("小明",16,90.5);
2.Student stu2 = stu1;
3.Student stu3(stu1);
当然,你也可以再添加一个参数为const 引用的拷贝构造函数,这样就不会出错了。

换句话说,一个类可以同时存在两个拷贝构造函数,一个函数的参数为const 引用,另一个函数的参数为非const 引用。

默认拷贝构造函数
在前面的教程中,我们还没有讲解拷贝构造函数,但是却已经在使用拷贝的方式创建对象了,并且也没有引发什么错误。

这是因为,如果程序员没有显式地定义拷贝构造函数,那么编译器会自动生成一个默认的拷贝构造函数。

这个默认的拷贝构造函数很简单,就是使用“老对象”的成员变量对“新对象”的成员变量进行一一赋值,和上面Student 类的拷贝构造函数非常类似。

对于简单的类,默认拷贝构造函数一般是够用的,我们也没有必要再显式地定义一个功能类似的拷贝构造函数。

但是当类持有其它资源时,如动态分配的内存、打开的文件、指向其他数据的指针、网络连接等,默认拷贝构造函数就不能拷贝这些资源,我们必须显式地定义拷贝构造函数,以完整地拷贝对象的所有数据,这点我们将在《C++深拷贝和浅拷贝》一节中深入讲解。

相关文档
最新文档