C++中拷贝构造函数的应用详解_C 语言

一、C++中拷贝构造函数的定义:

有一个参数的类型是其类类型的构造函数是为拷贝构造函数。
如下所示:

X::X( const X& x);
Y::Y( const Y& y, int =0 );
//可以是多参数形式,但其第二个即后继参数都有一个默认值 

二、拷贝构造函数的应用:

当一个类对象以另一个同类实体作为初值时,大部分情况下会调用拷贝构造函数。 一般是这三种具体情况:

1.显式地以一个类对象作为另一个类对象的初值,形如X xx=x;
2.当类对象被作为参数交给函数时。
3.当函数返回一个类对象时。

后两种情形会产生一个临时对象。

三、C++中编译器何时合成拷贝构造函数

并不是所有未定义有拷贝构造函数的类编译器都会为其合成拷贝构造函数,编译器只有在必要的时候才会为其合成拷贝构造函数。所谓必要的时刻是指编译器在普通手段无法完成解决“当一个类对象以另一个同类实体作为初值”时,才会合成拷贝构造函数。也就是说,当常规手段能解决问题的时候,就没必要动用非常规手段。

如果一个类没有定义拷贝构造函数,通常按照“成员逐一初始化(Default Memberwise Initialization)”的手法来解决“一个类对象以另一个同类实体作为 初值”——也就是说把内建或派生的数据成员从某一个对象拷贝到另一个对象身上,如果数据成员是一个对象,则递归使用“成员逐一初始化(Default Memberwise Initialization)”的手法。

成员逐一初始化(Default Memberwise Initialization)具体的实现方式则是位 逐次拷贝(Bitwise copy semantics)1。也就是说在能使用这种常规方式 来解决“一个类对象以另一个同类实体作为初值”的时候,编译器是不需要合成拷 贝构造函数的。但有些时候常规武器不那么管用,我们就得祭出非常规武器了 ——拷贝构造函数。有以下几种情况之一,位逐次拷贝将不能胜任或者不适合来完成“一个类对象以另一个同类实体作为初值”的工作。此时,如果类没有定义拷贝 构造函数,那么编译器将必须为类合成一个拷贝构造函数。

当类内含一个成员对象,而后者的类声明有一个拷贝构造函数时(不论是设 计者定义的还是编译器合成的)。
当类继承自一个声明有拷贝构造函数的类时(同样,不论这个拷贝构造函数 是被显示声明还是由编译器合成的)。

四、类中声明有虚函数

当类的派生串链中包含有一个或多个虚基类。
对于前两种情况,不论是基类还是对象成员,既然后者声明有拷贝构造函数时, 就表明其类的设计者或者编译器希望以其声明的拷贝构造函数来完成“一个类对象 以另一个同类实体作为初值”的工作,而设计者或编译器这样做——声明拷贝构造函 数,总有它们的理由,而通常最直接的原因莫过于因为他们想要做一些额外的工 作或“位逐次拷贝”无法胜任。

对于有虚函数的类,如果两个对象的类型相同那么位逐次拷贝其实是可以胜任的。但问题将出现在,如果基类由其继承类进行初始化时,此时若按照位逐次拷贝来完成这个工作,那么基类的vptr将指向其继承类的虚函数表,这将导致无法预料的后果——调用一个错误的虚函数实体是无法避免的,轻则带来程序崩溃,更糟糕的问题可能是这个错误被隐藏了。所以对于有虚函数的类编译器将会明确的使被 初始化的对象的vptr指向正确的虚函数表。因此有虚函数的类没有声明拷贝构造 函数,编译将为之合成一个,来完成上述工作,以及初始化各数据成员,声明有 拷贝构造函数的话也会被插入完成上述工作的代码。

对于继承串链中有虚基类的情况,问题同样出现在继承类向基类提供初值的情况, 此时位逐次拷贝有可能破坏对象中虚基类子对象的位置。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索c++
, 应用
, 拷贝
构造函数
拷贝构造函数、c 拷贝构造函数、默认拷贝构造函数、拷贝构造函数的作用、java拷贝构造函数,以便于您获取更多的相关知识。

时间: 2024-11-03 05:04:52

C++中拷贝构造函数的应用详解_C 语言的相关文章

C++中拷贝构造函数的总结详解_C 语言

1.什么是拷贝构造函数: 拷贝构造函数嘛,当然就是拷贝和构造了.(其实很多名字,只要静下心来想一想,就真的是顾名思义呀)拷贝又称复制,因此拷贝构造函数又称复制构造函数.百度百科上是这样说的:拷贝构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化.其唯一的参数(对象的引用)是不可变的(const类型).此函数经常用在函数调用时用户定义类型的值传递及返回. 2.拷贝构造函数的形式 复制代码 代码如下: Class X{public: X(); X(const

深入C++拷贝构造函数的总结详解_C 语言

拷贝构造函数是C++最基础的概念之一,大家自认为对拷贝构造函数了解么?请大家先回答一下三个问题:1. 以下函数哪个是拷贝构造函数,为什么?X::X(const X&);   X::X(X);   X::X(X&, int a=1);   X::X(X&, int a=1, b=2);  2. 一个类中可以存在多于一个的拷贝构造函数吗?3. 写出以下程序段的输出结果, 并说明为什么? 如果你都能回答无误的话,那么你已经对拷贝构造函数有了相当的了解. #include <iost

基于c++中的默认拷贝函数的使用详解_C 语言

<c++编程思想>上说一个类如果没有拷贝函数,那么编译器就会自动创建一个默认的拷贝函数.下面就让我们看一下真实的情况. 首先看一个简单的类X,这个类没有显示定义拷贝构造函数. c++源码如下: 复制代码 代码如下: class X {private:    int i;    int j;}; int main() {    X x1;//先定义对象x1    X x2 = x1;//将x1拷贝给x2} 下面是其汇编代码: 复制代码 代码如下: _main    PROC ; 7    : i

C++中宏的使用问题详解_C 语言

宏不遵循C++中关于范围和类型的规则.这经常导致一些微妙的或不那么微妙的问题.因此,C++提供更适合其他的C++(译注:原文为the rest of C++,当指C++除了兼容C 以外的部分)的替代品,例如内联函数.模板与名字空间. 考虑一下: #include "someheader.h" struct S { int alpha; int beta; }; 如果某人(不明智地)地写了一个叫"alpha"或"beta"的宏,那么它将不会被编译,

C++构造函数初始化顺序详解_C 语言

1.构造函数.析构函数与拷贝构造函数介绍 构造函数 1.构造函数不能有返回值 2.缺省构造函数时,系统将自动调用该缺省构造函数初始化对象,缺省构造函数会将所有数据成员都初始化为零或空 3.创建一个对象时,系统自动调用构造函数 析构函数 1.析构函数没有参数,也没有返回值.不能重载,也就是说,一个类中只可能定义一个析构函数 2.如果一个类中没有定义析构函数,系统也会自动生成一个默认的析构函数,为空函数,什么都不做 3.调用条件:1.在函数体内定义的对象,当函数执行结束时,该对象所在类的析构函数会被

C++中的const和constexpr详解_C 语言

C++中的const可用于修饰变量.函数,且在不同的地方有着不同的含义,现总结如下. const的语义 C++中的const的目的是通过编译器来保证对象的常量性,强制编译器将所有可能违背const对象的常量性的操作都视为error. 对象的常量性可以分为两种:物理常量性(即每个bit都不可改变)和逻辑常量性(即对象的表现保持不变).C++中采用的是物理常量性,例如下面的例子: struct A { int *ptr; }; int k = 5, r = 6; const A a = {&k};

MFC中Radio Button的用法详解_C 语言

本文通过针对两个常见问题的解决方案,详细阐述了MFC中Radio Button的用法.有助于读者加深对于MFC运行机制及Radio Button控件用法的理解. 首先为对话框加上2个radio button,分别是Radio1和Radio2. 问题1:如何让Radio1或者Radio2默认选上?如何知道哪个被选上了? 关键是选上,"默认"只要放在OnInitDialog()即可.有如下的三种方法可以让它选上: 第一种: ((CButton *)GetDlgItem(IDC_RADIO1

VC++中的字体设置方法详解_C 语言

VC++中static text字体改变 窗口都有2个和字体有关的函数:CWnd::GetFont()和SetFont(CFont*, BOOL);1)CFont* pFont = m_static.GetFont(); 2)LOGFONT LogFont;pFont->GetLogFont(&LogFont); 3)对LogFont直接操纵修改里面的字体选项 //如LogFont.lfUnderline = 1;设置下划线 LogFont.lfHeight=30;       //字体大小

c语言中 基于随机函数的使用详解_C 语言

在C语言中,rand()函数可以用来产生随机数,但是这不是真真意义上的随机数,是一个伪随机数,是根据一个数,我们可以称它为种子,为基准以某个递推公式推算出来的一系数,当这系列数很大的时候,就符合正态公布,从而相当于产生了随机数,但这不是真正的随机数,当计算机正常开机后,这个种子的值是定了的,除非你破坏了系统,为了改变这个种子的值,C提供了srand()函数,它的原形是void srand( int a). 可能大家都知道C语言中的随机函数random,可是random函数并不是ANSI C标准,