接下来我将持续更新“深度解读《深度探索C 对象模型》”系列,敬请期待,欢迎关注!也可以关注公众号:iShare爱分享,自动获得推文。
写作不易,请有心人到我的公众号上点点赞支持一下,增加一下热度,也好让更多的人能看到,公众号里有完整的文章列表可供阅读。
有以下三种情况,一个类对象的初始化是以同一类型的另一个对象为初值。
第一种情况,定义一个类对象时以另一个对象作为初始值,如下:
代码语言:cpp复制class Foo {};
Foo a;
Foo b = a;
第二种情况,当调用一个函数时,这个函数的参数要求传入一个类对象:
代码语言:cpp复制class Foo {};
void Bar(Foo obj) {}
Foo a;
Bar(a);
第三种情况,是函数里返回一个类的对象:
代码语言:cpp复制class Foo {};
Foo Bar() {
Foo x;
// ...
return x;
}
这几种情况都是用一个类对象做为另一个对象的初值,假如这个类中有定义了拷贝构造函数,那么这时就会调用这个类的拷贝构造函数。但是如果类中没有定义拷贝构造函数,那么又会是怎样?很多人可能会认为编译器会生成一个拷贝构造函数来拷贝其中的内容,那么事实是否如此呢?
C 标准里描述到,如果一个类没有定义拷贝构造函数,那么编译器就会隐式地声明一个拷贝构造函数,它会判断这个拷贝构造函数是nontrivial(有用的、不平凡的)还是trivial(无用的、平凡的),只有nontrivial的才会显式地生成出来。那么怎么判断是trivial还是nontrivial的呢?编译器是根据这个类是否展现出有逐位/逐成员拷贝的语意,那什么是有逐位/逐成员拷贝的语意?来看看下面的例子。
有逐位拷贝语意的情形
代码语言:cpp复制#include <string.h>
#include <stdio.h>
class String {
public:
String(const char* s) {
if (s) {
len = strlen(s);
str = new char[len 1];
memcpy(str, s, len);
str[len] = '