拷贝构造函数
来源:互联网 发布:php短信验证码生成 编辑:程序博客网 时间:2024/06/04 00:20
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
class X {
public:
//X(){};
X(const X& a){std::cout<<"haha..."<<std::endl;};
~X(){std::cout<<"~X()..."<<std::endl;};
};
编译:error C2512: “X”: 没有合适的默认构造函数可用
如果在类中根本没有构造函数,编译器将自动地创建一个缺省的构造函数。不过在这种情况下,这个构造函数什么也不做。然而,如果我们加了一个拷贝构造函数,我们就告诉了编译器我们将自己处理构造函数的创建,编译
器将不再为我们创建缺省的构造函数。并且除非我们显式地创建一个缺省的构造函数,否则,编译器会指示出错。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//: C11:HowMany2.cpp
// The copy-constructor
#include <fstream>
#include <string>
using namespace std;
ofstream out("HowMany2.out");
class HowMany2 {
string name; // Object identifier
static int objectCount;
public:
HowMany2(const string& id = "") : name(id) {
++objectCount;
print("HowMany2()");
}
~HowMany2() {
--objectCount;
print("~HowMany2()");
}
// The copy-constructor:
HowMany2(const HowMany2& h) : name(h.name) {
name += " copy";
++objectCount;
print("HowMany2(const HowMany2&)");
}
void print(const string& msg = "") const {
if(msg.size() != 0)
out << msg << endl;
out << '/t' << name << ": "
<< "objectCount = "
<< objectCount << endl;
}
};
int HowMany2::objectCount = 0;
// Pass and return BY VALUE:
HowMany2 f(HowMany2 x) {
x.print("x argument inside f()");
out << "Returning from f()" << endl;
return x;
}
int main() {
HowMany2 h("h");
out << "Entering f()" << endl;
HowMany2 h2 = f(h);
//h值传递,先调用拷贝构造函数
// 在退出函数前,需先将x拷贝到外面的返回值处,因此先调用拷贝构造函数,从h copy拷贝,最后才调用x的析构函数
h2.print("h2 after call to f()");
out << "Call f(), noreturn value" << endl;
f(h);
// 首先拷贝构造,尽管忽略了返回值,但在调用之前就将返回值的地址入栈了,
因此编译器需要创建一个临时对象,在退出之前,将h copy复制到临时对象中,
最后释放局部对象h copy,函数返回后,语句执行完毕,临时对象无用,析构释放
out << "After call to f()" << endl;
按照构造的相反顺序析构
} ///:~
1) HowMany2()
2)h: objectCount = 1
3) Entering f()
4) HowMany2(const HowMany2&)
5)h copy: objectCount = 2
6) x argument inside f()
7)h copy: objectCount = 2
8) Returning from f()
9) HowMany2(const HowMany2&)
10)h copy copy: objectCount = 3
11) ~HowMany2()
12)h copy: objectCount = 2
13) h2 after call to f()
14)h copy copy: objectCount = 2
15) Call f(), no return value
16) HowMany2(const HowMany2&)
17)h copy: objectCount = 3
18) x argument inside f()
19)h copy: objectCount = 3
20) Returning from f()
21) HowMany2(const HowMany2&)
22)h copy copy: objectCount = 4
23) ~HowMany2()
24)h copy: objectCount = 3
25) ~HowMany2()
26)h copy copy: objectCount = 2
27) After call to f()
28) ~HowMany2()
29)h copy copy: objectCount = 1
30) ~HowMany2()
31)h: objectCount = 0
此间要注意临时变量的创建和销毁。
临时对象
1 5行开始调用f ( h ),这次调用忽略了返回值。在1 6行可以看到恰好在参数传入之前,拷贝
构造函数被调用。和前面一样, 2 1行显示了为返回值而调用拷贝构造函数。但是,拷贝构造函
数必须有一个作为它的目的地( t h i s指针)的工作地址。对象返回到哪里?
每当编译器需要正确地计算一个表达式时,编译器可以创建一个临时对象。在这种情况下,
编译器创建一个我们甚至看不见的对象作为函数f( )忽略了的返回值的目的地地址。这个临时
对象的生存期应尽可能地短,这样,空间就不会被这些等待被销毁且占珍贵资源的临时对象搞
乱。在一些情况下,临时对象可能立即传递给另外的函数。但在现在这种情况下,在函数调用
之后,不需要临时对象,所以一旦函数调用以对内部对象调用析构函数( 2 3和2 4行)的方式结
束,临时对象就被销毁(2 5和2 6行)。在2 8 - 3 1行,对象h 2被销毁了,接着对象h被销毁。对象记数非常正确地回到了0。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
默认拷贝函数的使用
只有在需要值传递时才需要拷贝构造函数。为了防止编译器为你自动生成拷贝构造函数导致问题,可以声明一个私有的拷贝构造函数,若成员函数或者friend函数不进行值传递的话,甚至不需要定义拷贝构造函数。这样编译器不会为你自动生成,但同时你自己定义的为私有函数,编译器不能调用,因此会告警。
//: C11:NoCopyConstruction.cpp
// Preventing copy-construction
class NoCC {
int i;
NoCC(const NoCC&); // No definition
public:
NoCC(int ii = 0) : i(ii) {}
};
void f(NoCC);
int main() {
NoCC n;
//! f(n); // Error: copy-constructor called
//! NoCC n2 = n; // Error: c-c called
//! NoCC n3(n); // Error: c-c called
} ///:~
- 构造函数、拷贝构造函数
- 拷贝构造函数,构造函数
- 拷贝构造函数--默认拷贝构造函数
- 构造、拷贝构造函数基础
- 拷贝构造函数 深拷贝 浅拷贝
- 拷贝构造函数(深拷贝,浅拷贝)
- 拷贝构造函数浅拷贝深拷贝
- 拷贝构造函数,浅拷贝,深拷贝
- 拷贝构造函数 深拷贝 浅拷贝
- 拷贝构造函数----深拷贝、浅拷贝
- 拷贝构造函数
- 拷贝构造函数
- 浅析拷贝构造函数
- 拷贝构造函数
- 拷贝构造函数
- C++拷贝构造函数
- C++拷贝构造函数
- 拷贝构造函数
- LINUX卸载系统自带JDK 很给力的文章
- 如何将数据库中的表导入到PowerDesigner中
- HTTP 502 错误 – 网关错误 (Bad gateway)
- vs2008中Qt提示设置
- STL算法学习
- 拷贝构造函数
- Vc++(MFC)中怎样使用ADO Data控件实现与SQL Server的(远程)连接(ADO实现)
- 软件工程师职业规划
- JS中instanceof跟typeof的区别
- Lisp笔记--第四章-语法语义
- 一、编译,运行 并且 理解 你的 第一个 c程序
- 随手记,就算当围脖用吧
- 二、编译,运行 并且 理解 你的第一个c程序(二)
- Java定时更新数据---定时器