当没有编写时,编译器一定会生成拷贝构造函数,赋值函数 吗?
2014-09-02 15:37
288 查看
一般说来,C++ 编译器会为我们生成四个函数,默认构造函数,析构函数,拷贝构造函数,赋值函数,如果我们没有声明它们的话。
但情况真的是这样的吗?不,这不是永恒的真理!
首先,明确一点,上面的函数没有声明时,编译器只在认为它们有必要被创建时才去创建,具体而言:
对于构造函数:
只有以下四种情况下会合成默认构造函数(且只会在需要被调用时才合成):
1.某一个成员含有constructor,不论这个函数是用户自己写的,还是编译器生成的。因为编译器必须生成一个构造函数并在里面安放调用那个成员的构造函数的代码,如果有多个成员, 则以它们的声明顺序去调用。
class B
{
char *str;//初始化这个变量不是编译器的事情,不会在合成的构造函数里面初始化它。
Foo foo;
B()
//如果不存在任何构造函数,则会生成下面这个构造函数
{
foo.Foo::Foo();
//安插 foo 的构造代码
}
//如果用户定义了构造函数,则会在每个已定义的构造函数里面,安插 foo 的构造代码
}
2.类的基类带有 constructor ,不论这个函数是用户自己写的,还是编译器生成的。编译器必须生成一个构造函数并在里面安放调用基类的构造函数的代码(比调用成员的构造函数要早)。
不再举例,与 1 类似。
3.带有一个 virutual Function ,此时,这个类需要保存一个虚表指针 pvtbl 用于指向虚函数表 vtbl,vtbl 里面存放的是各个虚函数的函数指针。pvtbl 暗含在类中,它在构造函数最开始的地方被初始化指向那个 vtbl。
4.带有一个 "Virtual Base Class"的 class,如菱形继承
class X{ int i; };
class A : public virtual X{};
class B : public virtual X{};
class C : public A,public B{};
在这个继承体系中,如果有这样的代码:
A * pa;
pa -> i = 1;
则 pa -> i 的这个数据必须要在运行时,才能决议出它的地址,因为 A* 的动态类型可能是 C,在 C 里面,i 的地址是不确定的,必须要在 A 的构造函数,且在里面合成一个指针,指向具体类型。
另外,需要注意一点,在合成的 defalt construtor 中,只有 base class subobjects 和 member class objects 会被初始化,所有其它的 nonstatic data member,如整数,整数指针,整数数组等都不会被初始化,因为它们对于编译器来说完全是没有必要的。
但情况真的是这样的吗?不,这不是永恒的真理!
首先,明确一点,上面的函数没有声明时,编译器只在认为它们有必要被创建时才去创建,具体而言:
对于构造函数:
只有以下四种情况下会合成默认构造函数(且只会在需要被调用时才合成):
1.某一个成员含有constructor,不论这个函数是用户自己写的,还是编译器生成的。因为编译器必须生成一个构造函数并在里面安放调用那个成员的构造函数的代码,如果有多个成员, 则以它们的声明顺序去调用。
class B
{
char *str;//初始化这个变量不是编译器的事情,不会在合成的构造函数里面初始化它。
Foo foo;
B()
//如果不存在任何构造函数,则会生成下面这个构造函数
{
foo.Foo::Foo();
//安插 foo 的构造代码
}
//如果用户定义了构造函数,则会在每个已定义的构造函数里面,安插 foo 的构造代码
}
2.类的基类带有 constructor ,不论这个函数是用户自己写的,还是编译器生成的。编译器必须生成一个构造函数并在里面安放调用基类的构造函数的代码(比调用成员的构造函数要早)。
不再举例,与 1 类似。
3.带有一个 virutual Function ,此时,这个类需要保存一个虚表指针 pvtbl 用于指向虚函数表 vtbl,vtbl 里面存放的是各个虚函数的函数指针。pvtbl 暗含在类中,它在构造函数最开始的地方被初始化指向那个 vtbl。
4.带有一个 "Virtual Base Class"的 class,如菱形继承
class X{ int i; };
class A : public virtual X{};
class B : public virtual X{};
class C : public A,public B{};
在这个继承体系中,如果有这样的代码:
A * pa;
pa -> i = 1;
则 pa -> i 的这个数据必须要在运行时,才能决议出它的地址,因为 A* 的动态类型可能是 C,在 C 里面,i 的地址是不确定的,必须要在 A 的构造函数,且在里面合成一个指针,指向具体类型。
另外,需要注意一点,在合成的 defalt construtor 中,只有 base class subobjects 和 member class objects 会被初始化,所有其它的 nonstatic data member,如整数,整数指针,整数数组等都不会被初始化,因为它们对于编译器来说完全是没有必要的。
相关文章推荐
- 条款6:阻止编译器自动生成拷贝构造函数和赋值函数
- 编译器肯定会为没有constructor的类生成一..
- 编写String类的普通构造函数、拷贝构造函数、析构函数、赋值函数
- 用C#编写的代码经C#编译器后,并非生成本地代码而是生成托管代码
- 编写类String的构造函数、拷贝构造函数、析构函数、赋值函数
- 字符串strcpy函数的实现,以及字符串string的实现,编写构造函数,拷贝构造函数,赋值函数,析构函数
- 明确拒绝不想编译器自动生成的拷贝构造函数和赋值运算符重载函数
- 详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数
- 面试题目6 编写类String的构造函数、拷贝构造函数、析构函数、赋值函数
- 编写类String的构造函数、拷贝构造函数、析构函数和赋值函数
- 编写String的构造函数、析构函数、拷贝构造函数、赋值函数
- 编写String类的构造函数、析构函数、拷贝构造函数、赋值函数
- 第五篇:明确拒绝不想编译器自动生成的拷贝构造函数和赋值运算符重载函数
- 编译器肯定会为没有constructor的类生成一个default constructor吗? ——感叹国内教科书中的常识性错误 推荐
- 编写类String的构造函数、拷贝构造函数、析构函数和赋值函数
- 编写类String 的构造函数、拷贝构造函数、析构函数和赋值函数
- 编写string类的构造函数、拷贝构造函数、析构函数、赋值函数
- 用TCL编写了一个生成密码字典的小测试程序,共享一下
- 编写Powerdesigner脚本,快速生成数据库表
- 没有ORM或代码生成数据就不能持久化了? - 用范型技术代替代码生成!