【重要】C++拷贝函数详解 20150111
- 格式:docx
- 大小:8.25 KB
- 文档页数:5
c语言文件拷贝函数摘要:1.文件拷贝函数的背景和意义2.文件拷贝函数的原理3.文件拷贝函数的实现4.文件拷贝函数的应用场景5.文件拷贝函数的性能和优化正文:C语言是一种广泛应用于系统编程和应用开发的编程语言,它提供了丰富的文件操作函数,包括文件读写、文件定位等。
在这些函数中,文件拷贝函数是实现文件传输和备份的重要工具。
本文将详细介绍C语言文件拷贝函数的相关知识。
文件拷贝函数的原理是通过读取源文件的数据,将其写入目标文件。
在C 语言中,有两个常用的文件拷贝函数:fread()和fcopy()。
其中,fread()函数用于从文件中读取数据,fcopy()函数用于将数据从源文件拷贝到目标文件。
文件拷贝函数的实现过程可以分为以下几个步骤:1.打开源文件和目标文件,如果目标文件不存在,需要创建目标文件。
2.使用fread()函数从源文件中读取数据,将数据存储在缓冲区。
3.使用fwrite()函数将缓冲区中的数据写入目标文件。
4.重复步骤2和3,直到文件结束。
5.关闭源文件和目标文件。
文件拷贝函数的应用场景包括:1.文件备份:将重要的文件拷贝到另一个地方,以防数据丢失。
2.文件传输:在不同设备之间传输文件。
3.文件合并:将多个文件合并成一个文件。
文件拷贝函数的性能和优化主要取决于磁盘IO性能和CPU性能。
为了提高文件拷贝速度,可以采用以下方法:1.使用多线程或多进程并行拷贝,充分利用CPU资源。
2.使用内存映射文件技术,将文件数据映射到内存,减少磁盘IO次数。
3.对大文件进行分块拷贝,减小单次读写的数据量,提高磁盘缓存利用率。
总之,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) 就是我们⾃定义的拷贝构造函数。
c语言文件拷贝函数【引言】在C语言编程中,文件操作是一项非常重要的技能。
文件拷贝功能在实际项目中也有着广泛的应用。
本文将介绍C语言中的文件拷贝函数,详细说明其实现原理,并通过示例代码加深理解。
同时,针对文件拷贝过程中可能遇到的问题,给出解决方案和注意事项。
【C语言文件拷贝函数概述】C语言中,文件拷贝函数通常使用系统调用函数实现。
常用的系统调用函数有`copy_file`、`fcopy`等。
这些函数可以实现将一个文件的内容拷贝到另一个文件中。
以下为部分系统调用函数的原型:- copy_file(Linux系统):```int copy_file(int src_fd, int dst_fd, unsigned long long size);```- fcopy(POSIX系统):```ssize_t fcopy(FILE *src, FILE *dst, size_t size);```【文件拷贝函数实现原理】文件拷贝函数的核心思想是通过读取源文件的内容,逐字节写入目标文件。
在实现过程中,需要考虑以下几个方面:1.文件描述符:源文件和目标文件的文件描述符。
2.缓冲区:用于临时存储从源文件读取的内容。
3.读写操作:通过系统调用函数,实现从源文件读取数据到缓冲区,然后将缓冲区数据写入目标文件。
4.错误处理:检查拷贝过程中可能出现的错误,如文件描述符错误、缓冲区溢出等。
【文件拷贝函数示例】以下为一个简单的C语言文件拷贝函数示例:```c#include <stdio.h>#include <stdlib.h>#include <unistd.h>ssize_t copy_file(const char *src_path, const char *dst_path, size_t size) {FILE *src_file = fopen(src_path, "rb");if (src_file == NULL) {perror("Failed to open source file");return -1;}FILE *dst_file = fopen(dst_path, "wb");if (dst_file == NULL) {perror("Failed to create destination file");fclose(src_file);return -1;}char buffer[size] = {0};size_t read_size;while ((read_size = fread(buffer, 1, size, src_file)) > 0) { fwrite(buffer, 1, read_size, dst_file);}fclose(src_file);fclose(dst_file);return 0;}int main() {const char *src_path = "source.txt";const char *dst_path = "destination.txt";size_t size = 1024;if (copy_file(src_path, dst_path, size) == 0) {printf("File copied successfully");} else {printf("Failed to copy file");}return 0;}```【常见问题及解决方案】1.文件描述符错误:检查源文件和目标文件是否正确打开或创建。
c++拷贝构造函数(重点在内含指针的浅拷贝和深拷贝)今天同事问了⼀个关于拷贝构造函数的问题,类中包含指针的情况,今天就来说说c++的拷贝构造函数。
c++的拷贝构造函数是构造函数的⼀种,是对类对象的初始化,拷贝构造函数只有⼀个参数就是本类的引⽤。
注意,默认构造函数(即⽆参构造函数)不⼀定存在,但是拷贝构造函数总是会存在。
下⾯是⼀个拷贝构造函数的例⼦。
1 #include<iostream>2using namespace std;3class A{4public:5int a;6 A(int value){7 a = value;8 }9void show(){10 cout<<a<<endl;11 }12 };13int main(){14 A test_a(10);15 test_a.show();1617 A test_b(test_a);18 test_b.show();1920return0;21 }输出结果为:1010如果编写了拷贝构造函数,则默认拷贝构造函数就不存在了。
下⾯是⼀个⾮默认拷贝构造函数的例⼦。
1 #include<iostream>2using namespace std;3class A{4public:5int a;6 A(int value){7 a = value;8 }9 A(A& tmp){10 a = tmp.a;11 cout<<"call copy construct"<<endl;12 }13void show(){14 cout<<a<<endl;15 }16 };17int main(){18 A test_a(10);19 test_a.show();2021 A test_b(test_a);22 test_b.show();2324return0;25 }输出结果为:10call copy construct10拷贝构造函数在以下三种情况下会被调⽤。
c语言字符串拷贝函数C语言字符串拷贝函数在C语言中,字符串是一种常见的数据类型,它由字符组成的字符数组。
在处理字符串时,我们经常需要拷贝一个字符串到另一个字符串中。
为了实现这个功能,C语言提供了一个字符串拷贝函数——strcpy()。
strcpy()函数的原型如下:```char* strcpy(char* destination, const char* source);```该函数接受两个参数,第一个参数是目标字符串的指针,第二个参数是源字符串的指针。
函数的作用是将源字符串拷贝到目标字符串中,并返回目标字符串的指针。
在使用strcpy()函数时,我们需要注意以下几点:1. 目标字符串的长度要足够长,以容纳源字符串的内容。
如果目标字符串长度不够,可能会导致内存溢出的问题。
2. 源字符串必须以空字符('\0')结尾,否则拷贝的结果将不正确。
下面是一个使用strcpy()函数进行字符串拷贝的示例:```#include <stdio.h>#include <string.h>int main() {char source[] = "Hello, world!";char destination[20];strcpy(destination, source);printf("拷贝后的字符串:%s\n", destination);return 0;}```在上述示例中,我们首先定义了源字符串source和目标字符串destination。
然后使用strcpy()函数将source拷贝到destination 中。
最后,我们使用printf()函数打印出拷贝后的字符串。
运行上述代码,输出结果为:```拷贝后的字符串:Hello, world!```除了strcpy()函数,C语言还提供了一些类似的字符串拷贝函数,如strncpy()和memcpy()。
C拷贝构造函数的⼏个知识点总结及⽰例代码C++拷贝构造函数的知识点总结⼀拷贝构造函数是C++最基础的概念之⼀,⼤家⾃认为对拷贝构造函数了解么?请⼤家先回答⼀下三个问题:1.以下函数哪个是拷贝构造函数,为什么?1.X::X(const X&);2.X::X(X);3.X::X(X&, int a=1);4.X::X(X&, int a=1, b=2);2.⼀个类中可以存在多于⼀个的拷贝构造函数吗?3.写出以下程序段的输出结果, 并说明为什么?如果你都能回答⽆误的话,那么你已经对拷贝构造函数有了相当的了解。
1.#include2.#include3.4.struct X {5. template6. X( T& ) { std::cout << "This is ctor." << std::endl; }7.8. template9. X& operator=( T& ) { std::cout << "This is ctor." << std::endl; }10.};11.12.void main() {13. X a(5);14. X b(10.5);15. X c = a;16. c = b;17.}解答如下:1.对于⼀个类X,如果⼀个构造函数的第⼀个参数是下列之⼀:a) X&b) const X&c) volatile X&d) const volatile X&且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数.1.X::X(const X&); //是拷贝构造函数2.X::X(X&, int=1); //是拷贝构造函数2.类中可以存在超过⼀个拷贝构造函数,1.class X {2.public:3. X(const X&);4. X(X&); // OK5.};注意,如果⼀个类中只存在⼀个参数为X&的拷贝构造函数,那么就不能使⽤const X或volatile X的对象实⾏拷贝初始化.1.class X {2.public:3. X();4. X(X&);5.};6.7.const X c x;8.X x = c x; // error如果⼀个类中没有定义拷贝构造函数,那么编译器会⾃动产⽣⼀个默认的拷贝构造函数.这个默认的参数可能为X::X(const X&)或X::X(X&),由编译器根据上下⽂决定选择哪⼀个.默认拷贝构造函数的⾏为如下:默认的拷贝构造函数执⾏的顺序与其他⽤户定义的构造函数相同,执⾏先⽗类后⼦类的构造.拷贝构造函数对类中每⼀个数据成员执⾏成员拷贝(memberwise Copy)的动作.a)如果数据成员为某⼀个类的实例,那么调⽤此类的拷贝构造函数.b)如果数据成员是⼀个数组,对数组的每⼀个执⾏按位拷贝.c)如果数据成员是⼀个数量,如int,double,那么调⽤系统内建的赋值运算符对其进⾏赋值.3.拷贝构造函数不能由成员函数模版⽣成.1.struct X {2.template3. X( const T& ); // NOT copy ctor, T can't be X4.5.template6. operator=( const T& ); // NOT copy ass't, T can't be X7.};原因很简单, 成员函数模版并不改变语⾔的规则,⽽语⾔的规则说,如果程序需要⼀个拷贝构造函数⽽你没有声明它,那么编译器会为你⾃动⽣成⼀个. 所以成员函数模版并不会阻⽌编译器⽣成拷贝构造函数, 赋值运算符重载也遵循同样的规则.(参见Effective C++ 3edition, Item45)⼆针对上⾯作者的讨论,理解更深了,但是下⾯我还是会给出⼀个⼀般的标准的实现和注意事项:#include "stdafx.h"#include "stdio.h"#include#includestruct Test1{Test1() { }Test1(int i) { id = i; }Test1(const Test1& test){id = test.id;}Test1& operator = (const Test1& test) {if(this == &test)return *this;id = test.id;return *this;}int id;};class Test2{public:Test2(){ m_pChar = NULL;}Test2(char *pChar) { m_pChar = pChar;} Test2(int num){m_pChar = new char[num];for(int i = 0; i< num; ++i)m_pChar[i] = 'a';m_pChar[num-1] = '\0';Test2(const Test2& test){char *pCharT = m_pChar;m_pChar = new char[strlen(test.m_pChar)];strcpy(m_pChar, test.m_pChar);if(!pCharT)delete []pCharT;}Test2& operator = (const Test2& test){if(this == &test)return *this;char *pCharT = m_pChar;m_pChar = new char[strlen(test.m_pChar)];strcpy(m_pChar, test.m_pChar);if(!pCharT)delete []pCharT;return *this;}private:char *m_pChar;};int main(int argc, char* argv[]){const Test1 ts(1); // Test1()const Test1* p_ts = &tsconst Test1 ts2(ts); //Test(const Test1& test)const Test1 ts3 = ts; //Test(const Test1& test)Test1 ts4; ts4 = ts; //Test1& operator = (const Test1& test) Test2 t(5);Test2 t2(t);Test2 t3 = t2;Test2 t4; t4 = t;return 0;}。
c语言文件拷贝函数(原创实用版)目录1.C 语言文件拷贝函数的概述2.C 语言文件拷贝函数的实现3.C 语言文件拷贝函数的示例4.C 语言文件拷贝函数的注意事项正文【1.C 语言文件拷贝函数的概述】C 语言文件拷贝函数是一种用于复制文件的函数,可以将一个文件的内容复制到另一个文件中,为文件操作提供了便利。
在 C 语言中,可以使用标准库函数实现文件拷贝功能。
【2.C 语言文件拷贝函数的实现】C 语言文件拷贝函数的实现主要依赖于标准库函数`fopen`、`fgets`和`fclose`。
`fopen`函数用于打开文件,`fgets`函数用于读取文件内容,`fclose`函数用于关闭文件。
通过这三个函数的组合,可以实现文件拷贝功能。
【3.C 语言文件拷贝函数的示例】以下是一个简单的 C 语言文件拷贝函数示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>void copy_file(const char *source_file, const char*destination_file) {FILE *source = fopen(source_file, "rb");if (source == NULL) {printf("Error: cannot open source file.");return;}FILE *destination = fopen(destination_file, "wb");if (destination == NULL) {printf("Error: cannot open destination file.");fclose(source);return;}char buffer[1024];size_t read_size;while ((read_size = fgets(buffer, sizeof(buffer), source))!= 0) {fwrite(buffer, 1, read_size, destination);}fclose(source);fclose(destination);printf("File copied successfully.");}int main() {const char *source_file = "source.txt";const char *destination_file = "destination.txt";copy_file(source_file, destination_file);return 0;}```【4.C 语言文件拷贝函数的注意事项】在使用 C 语言文件拷贝函数时,需要注意以下几点:1.检查文件是否成功打开。
c语言拷贝文件函数-回复如何在C语言中使用拷贝文件函数在C语言中,拷贝文件函数是一种非常常用且有用的功能,它允许我们将一个文件的内容复制到另一个文件中。
这种操作在程序开发中非常实用,比如在数据备份、数据同步等场景中。
本文将一步一步地为你介绍如何使用C语言中的拷贝文件函数。
为了使用拷贝文件函数,我们首先需要了解函数的原型和参数。
在C语言中,拷贝文件函数的原型如下:cint copyFile(const char *sourceFile, const char *destinationFile);该函数接受两个参数:源文件和目标文件。
源文件是我们要复制内容的文件,而目标文件是我们将要把内容复制到的文件。
函数将返回一个整数值,用于指示拷贝操作是否成功。
如果成功,则返回0;否则返回一个非零值。
在了解了函数的原型后,我们可以开始使用拷贝文件函数。
以下是一个简单的示例代码,展示了如何使用拷贝文件函数来复制文件内容:c#include <stdio.h>int copyFile(const char *sourceFile, const char *destinationFile);int main() {const char *sourceFile = "source.txt";const char *destinationFile = "destination.txt";int result = copyFile(sourceFile, destinationFile);if (result == 0) {printf("文件拷贝成功!\n");} else {printf("文件拷贝失败!\n");}return 0;}int copyFile(const char *sourceFile, const char *destinationFile) { FILE *source = fopen(sourceFile, "rb"); 以二进制只读模式打开源文件FILE *destination = fopen(destinationFile, "wb"); 以二进制写入模式打开目标文件if (source == NULL destination == NULL) {return -1; 打开文件失败,返回非零值}int bufferSize = 1024; 缓冲区大小char buffer[bufferSize]; 缓冲区size_t bytesRead;while ((bytesRead = fread(buffer, sizeof(char), bufferSize, source)) > 0) {fwrite(buffer, sizeof(char), bytesRead, destination); 将缓冲区中的内容写入目标文件}fclose(source); 关闭源文件fclose(destination); 关闭目标文件return 0; 返回0表示拷贝成功}在上述示例代码中,我们首先定义了源文件和目标文件的文件路径。
c数组拷贝函数一、函数介绍本文将为大家介绍C语言中的数组拷贝函数,该函数可以用于将一个数组的所有元素拷贝到另一个数组中。
该函数的实现需要考虑到数组类型、数组长度以及内存分配等问题,因此需要注意相关细节。
二、函数原型在开始编写函数之前,我们先来确定一下该函数的原型。
根据需求,我们可以将该函数定义为以下形式:void array_copy(void *src, void *dest, size_t count);其中,src表示源数组的首地址,dest表示目标数组的首地址,count 表示需要拷贝的元素个数。
三、函数实现1. 判断数据类型在开始实现拷贝操作之前,我们需要先判断源数组和目标数组的数据类型是否相同。
如果数据类型不同,则无法进行拷贝操作。
因此,我们需要通过指针类型来判断两个数组是否具有相同的数据类型。
具体代码如下:if (sizeof(*src) != sizeof(*dest)) {printf("Error: Data type of source and destination arrays must be the same.\n");return;}2. 判断数据长度接下来,我们需要判断源数组和目标数组的长度是否相同。
如果两个数组长度不同,则无法进行完全拷贝操作。
因此,在进行拷贝操作之前,我们需要先判断两个数组的长度,并选择较小值作为实际拷贝元素个数。
具体代码如下:size_t len = (count < sizeof(src) / sizeof(*src)) ? count : sizeof(src) / sizeof(*src);3. 内存分配在确定了实际拷贝元素个数之后,我们需要为目标数组分配内存空间。
由于目标数组的长度可能小于源数组的长度,因此我们需要使用动态内存分配函数来为目标数组分配足够的内存空间。
具体代码如下:dest = malloc(len * sizeof(*dest));4. 拷贝操作在完成了内存分配之后,我们可以开始进行拷贝操作了。
c++类的拷贝、赋值与销毁(拷贝构造函数、拷贝赋值运算符和析构函数)拷贝构造函数如果⼀个构造函数的第⼀个参数是⾃⾝类类型的引⽤,且任何额外参数都有默认值,则此构造函数是拷贝构造函数。
拷贝构造函数第⼀个参数必须是⼀个引⽤类型。
此参数⼏乎总是⼀个const的引⽤。
拷贝构造函数在⼏种情况下都会被隐式地使⽤。
因此,拷贝构造函数通常不应该是explicit的。
合成拷贝构造函数与合成默认构造函数不同,即使我们定义了其他构造函数,编译器也会为我们合成⼀个拷贝构造函数。
对某些类来说,合成拷贝构造函数⽤来阻⽌我们拷贝该类类型的对象。
⽽⼀般情况,合成的拷贝构造函数会将其参数的成员逐个拷贝到正在创建的对象中。
每个成员的类型决定了它如何拷贝。
拷贝初始化直接初始化和拷贝初始化的差异。
string dots(10,','); //直接初始化string s(dots); //直接初始化string s2 = dots; //拷贝初始化当使⽤直接初始化时,我们实际上是要求编译器使⽤普通的函数匹配来选择与我们提供的参数最匹配的构造函数。
当我们使⽤拷贝初始化时,我们要求编译器将右侧运算对象拷贝到正在创建的对象中,如果需要的话还要进⾏类型转换。
拷贝初始化通常使⽤拷贝构造函数来完成。
拷贝初始化是依靠拷贝构造函数或移动构造函数来完成的。
拷贝初始化不仅在我们⽤=定义变量时会发⽣,在下列情况下也会发⽣•将⼀个对象作为实参传递给⼀个⾮引⽤类型的形参。
•从⼀个返回类型为⾮引⽤类型的函数返回⼀个对象。
•⽤花括号列表初始化⼀个数组中的元素或⼀个聚合类中的成员。
参数和返回值拷贝构造函数被⽤来初始化⾮引⽤类类型参数,这⼀特性解释了为什么拷贝构造函数⾃⼰的参数必须是引⽤类型。
如果其参数不是引⽤类型,则调⽤永远也不会成功——为了调⽤拷贝构造函数,我们必须拷贝它的实参,但为了拷贝实参,我们⼜必须调⽤拷贝构造函数,如此⽆限循环。
拷贝初始化的限制vector<int> v1(10); //直接初始化vector<int> v1 = 10; //错误:接受⼤⼩参数的构造函数是explicit的如果我们希望使⽤⼀个explicit构造函数,就必须显式的使⽤:void f(vector<int>); //f的参数进⾏拷贝初始化f(10); //错误:不能⽤⼀个explicit的构造函数拷贝⼀个实参f(vector<int>(10)); //正确:从⼀个int直接构造⼀个临时vector如果我们希望使⽤⼀个explicit构造函数,就必须显式的使⽤:编译器可以绕过拷贝构造函数编译器被允许将下⾯的代码string null_book = "9-999-99999-9";给写成string null_book("9-999-99999-9");//编译器略过了拷贝构造函数。
C++拷贝函数详解
1.什么是拷贝构造函数:
CA(const CA& C)就是我们自定义的拷贝构造函数。
可见,拷贝构造函数是一种特殊的构
造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量,该参
数是const类型,不可变的。
例如:类X的拷贝构造函数的形式为X(X& x)。
当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷
贝构造函数就会被自动调用。
也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用。
以下情况都会调用拷贝构造函数:
①程序中需要新建立一个对象,并用另一个同类的对象对它初始化,如前面介绍的那样。
②当函数的参数为类的对象时。
在调用函数时需要将实参对象完整地传递给形参,也就是需要建立一个实参的拷贝,这就
是按实参复制一个形参,系统是通过调用复制构造函数来实现的,这样能保证形参具有和实参
完全相同的值。
③函数的返回值是类的对象。
在函数调用完毕将返回值带回函数调用处时。
此时需要将函数中的对象复制一个临时对象并传给该函数的调用处。
如
Box f( ) //函数f的类型为Box类类型
{Box box1(12,15,18);
return box1; //返回值是Box类的对象
}
int main( )
{Box box2; //定义Box类的对象box2
box2=f( ); //调用f函数,返回Box类的临时对象,并将它赋值给
box2
}
如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的
拷贝构造函数,该构造函数完成对象之间的位拷贝。
位拷贝又称浅拷贝,后面将进行说明。
自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。
浅拷贝和深拷贝
在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的
值完全复制给另一个对象,如A=B。
这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。
这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。
深拷贝和浅拷贝可以简单理解为:
如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。
2.C++拷贝构造函数的几个细节
1) 以下函数哪个是拷贝构造函数,为什么?
1.X::X( const X&);
2.X::X(X);
3.X::X(X&, int a=1);
4.X::X(X&, int a=1, b=2);
解答:1) 对于一个类X,如果一个构造函数的第一个参数是下列之一:
a) X&
b) const X&
c) volatile X&
d) const volatile X&
且没有其他参数或其他参数都有默认值,那么这个函数是拷贝构造函数.
1.X::X( const X&); //是拷贝构造函数
2.X::X(X&, int =1); //是拷贝构造函数
2) 一个类中可以存在多于一个的拷贝构造函数吗?
解答:类中可以存在超过一个拷贝构造函数,
1.class X{
2.public :
3.X( const X&);
4.X(X&); // OK
5.};
【注意】
如果一个类中只存在一个参数为X&的拷贝构造函数,
那么就不能使用const X或volatile X的对象实行拷贝初始化.
1.class X{
2.public :
3.X();
4.X(X&);
5.};
6.
7.const X cx;
8.X x=cx; //error
如果一个类中没有定义拷贝构造函数,那么编译器会自动产生一个默认的拷贝构造函数.
这个默认的参数可能为X::X(const X&)或X::X(X&),由编译器根据上下文决定选择哪一个.
默认拷贝构造函数的行为如下:
默认的拷贝构造函数执行的顺序与其他用户定义的构造函数相同,
执行先父类后子类的构造.
拷贝构造函数对类中每一个数据成员执行成员拷贝(memberwise Copy)的动作.
a)如果数据成员为某一个类的实例,那么调用此类的拷贝构造函数.
b)如果数据成员是一个数组,对数组的每一个执行按位拷贝.
c)如果数据成员是一个数量,如int,double,那么调用系统内建的赋值运算符对其进行赋值.
3) 拷贝构造函数不能由成员函数模版生成.
struct X{
template < typename T>
X( const T& ); // NOT copy ctor, T can't be X
template < typename T>
operator=( const T& ); // NOT copy ass't, T can't be X
};
原因很简单, 成员函数模版并不改变语言的规则,而语言的规则说,如果程序需要一个拷贝构造函数而你没有声明它,那么编译器会为你自动生成一个. 所以成员函数模版并不会阻止编译器生成拷贝构造函数, 赋值运算符重载也遵循同样的规则
3.拷贝构造函数与赋值函数的异同:
1) 拷贝构造,是一个的对象来初始化一片内存区域,这片内存区域就是你的新对象的内存区域赋值运算,对于一个已经被初始化的对象来进行operator=操作
class A;
A a;
A b=a; //拷贝构造函数调用
//或
A b(a); //拷贝构造函数调用
///////////////////////////////////
A a;
A b;
b =a; //赋值运算符调用
你只需要记住,在C++语言里,
String s2(s1);
String s3 = s1;
只是语法形式的不同,意义是一样的,都是定义加初始化,都调用拷贝构造函数。
2)一般来说是在数据成员包含指针对象的时候,应付两种不同的处理需求的一种是复制指针对象,一种是引用指针对象 copy大多数情况下是复制,=则是引用对象的
例子:
class A
{
int nLen;
char * pData;
}
显然
A a, b;
a=b的时候,对于pData数据存在两种需求
第一种copy
a.pData = new char [nLen];
memcpy(a.pData, b.pData, nLen);
另外一种(引用方式):
a.pData =
b.pData
通过对比就可以看到,他们是不同的
往往把第一种用copy使用,第二种用=实现
你只要记住拷贝构造函数是用于类中指针,对象间的COPY
3)拷贝构造函数首先是一个构造函数,它调用的时候产生一个对象,是通过参数传进来
的那个对象来初始化,产生的对象。
operator=();是把一个对象赋值给一个原有的对象,所以如果原来的对象中有内存分配要先把内存释放掉,而且还要检查一下两个对象是不是同一个对象,如果是的话就不做任何操作。
还要注意的是拷贝构造函数是构造函数,不返回值
而赋值函数需要返回一个对象自身的引用,以便赋值之后的操作
4) 在形式上
类名(形参表列); //普通构造函数的声明,如Box(int h,int w,int len);
类名(类名& 对象名); //复制构造函数的声明,如Box(Box &b);
5) 在建立对象时,实参类型不同。
系统会根据实参的类型决定调用普通构造函数或复制
构造函数。
如:
Box box1(12,15,16); //实参为整数,调用普通构造函数
Box box2(box1);//实参是对象名,调用复制构造函数。