首页 > 其他分享 >58.类成员初始化方式?构造函数的执行顺序 ?为什么用成员初始化列表会快一些?

58.类成员初始化方式?构造函数的执行顺序 ?为什么用成员初始化列表会快一些?

时间:2023-07-04 22:44:06浏览次数:36  
标签:初始化 int 成员 列表 MyClass 构造函数

58.类成员初始化方式?构造函数的执行顺序 ?为什么用成员初始化列表会快一些?

1.类成员初始化方式

1.1初始化方式一:默认时初始化

如果类成员没有被显式初始化,将会使用默认初始化。默认初始化指没有提供初始化式的情况下,将使用默认值进行初始化。对于基本数据类型(如整数、浮点数等),默认值为0或空值(对于指针类型)。对于类类型,将会使用默认构造函数进行初始化。

class MyClass
{
public:
	int a;  // 默认初始化为0  
	MyClass() {}  // 默认构造函数  
};

1.2初始化方式二:声明时初始化(也称就地初始化,C++11后支持)

普通成员可以声明时初始化

class Aclass 
{
public:
	int mA = 1;// 声明时初始化
	Aclass()
	{
	}
};

1.3初始化方式三:构造函数初始化

1.默认构造函数:如果没有显式地定义构造函数,则编译器会自动生成一个默认构造函数。

2.带参数的构造函数:可以显式地定义一个或多个带参数的构造函数来初始化类成员。

3.拷贝构造函数:可以显式地定义一个拷贝构造函数来初始化类成员。

4.移动构造函数:可以显式地定义一个移动构造函数来初始化类成员。

5.赋值运算符重载:可以显式地定义赋值运算符重载来初始化类成员。

对于在函数体中初始化,是在所有的数据成员被分配内存空间后才进行的。

class MyClass 
{
public:
	int mA;
	MyClass(int a)
	{
		mA = a;
	}
};

1.4初始化方式四:值初始化

可以使用值初始化来指定类成员的初始值。值初始化使用括号将初始值括起来。

class MyClass
{
public:
	int mA;
	MyClass():mA(10)// 在初始化列表初始化mA的值
	{
	}
};

1.5初始化方式五:初始化列表

列表初始化是给数据成员分配内存空间时就进行初始化,就是说分配一个数据成员只要冒号后有此数据成员的赋值表达式(此表达式必须是括号赋值表达式),那么分配了内存空间后在进入函数体之前给数据成员赋值,就是说初始化这个数据成员此时函数体还未执行。

class MyClass 
{
public:
	int a;
	MyClass(int b) : a(b) {}  // 使用成员初始化列表指定初始值为参数b  
};

1.6初始化方式六:动态初始化

可以使用动态初始化在运行时为类成员分配内存并指定初始值。这种方式通常使用new运算符进行动态内存分配,然后使用初始化列表来指定初始值。

class MyClass 
{
public:
	int a;
	MyClass() { new(&a) int; }  // 使用动态初始化并为a分配内存,不指定初始值  
};

需要注意的是,对于类成员的初始化方式,应根据具体情况选择合适的方式。在一些情况下,使用默认初始化可能更加简洁和高效;而在其他情况下,显式初始化可能更明确和安全。

特例:

1.静态成员变量类内声明,类外初始化。

class MyClass
{
public:
	static int mA;// 类内声明
	MyClass()
	{
	}
};
int MyClass::mA = 1;// 类外初始化

2.非静态的常量如何初始化

只能在构造函数的初始化列表中初始化

int a = 1;
class MyClass
{
public:
	const int mA;
	MyClass():mA(a)// 在初始化列表初始化mA的值
	{
	}
};

3.静态常量整型数据成员

静态常量整型数据成员可以在类的声明中初始化,而且只有这种变量可以在类的声明中定义。

class MyClass
{
public:
	MyClass() {};
private:
	int a;
	int b;
	static const int sc_int = 10; //static const
};

2.一个派生类构造函数的执行顺序如下:

① 虚拟基类的构造函数(多个虚拟基类则按照继承的顺序执行构造函数)。

② 基类的构造函数(多个普通基类也按照继承的顺序执行构造函数)。

③ 类类型的成员对象的构造函数(按照成员对象在类中的定义顺序)

④ 派生类自己的构造函数。

构造函数的执行顺序可以分为以下几个步骤:

1.基类构造函数:首先执行基类的构造函数,确保基类对象被正确地初始化。如果基类还有基类,则依次递归执行基类构造函数。

2.成员变量初始化:对于每个成员变量,根据其在类中的声明顺序,使用初始化列表或赋值语句进行初始化。

3.成员函数:如果类中有成员函数,则在构造函数执行期间调用这些成员函数。这些成员函数可以访问类的成员变量,但不能修改它们。

4.派生类构造函数:最后执行派生类的构造函数,确保派生类对象被正确地初始化。如果派生类还有成员变量或成员函数,则按照声明顺序进行初始化。

需要注意的是,在构造函数执行期间,对象的成员变量可以被初始化,但不能被修改。此外,如果基类和派生类都有构造函数,那么在执行派生类构造函数之前,必须先执行基类的构造函数。这是因为派生类依赖于基类的基础设施,必须确保基类对象已经被正确地初始化。

继承中的构造和析构

42继承中的构造和析构1

#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
using namespace std;

class A {
public:
	A() {
		cout << "A类构造函数!" << endl;
	}
	~A() {
		cout << "A类析构函数!" << endl;
	}
};

class B : public A {
public:
	B() {
		cout << "B类构造函数!" << endl;
	}
	~B() {
		cout << "B类析构函数!" << endl;
	}
};

class C : public B {
public:
	C() {
		cout << "C类构造函数!" << endl;
	}
	~C() {
		cout << "C类析构函数!" << endl;
	}
};

void test() {
	C c;
}

int main()
{
	test();

	return 0;
}

输出:

A类构造函数!
B类构造函数!
C类构造函数!
C类析构函数!
B类析构函数!
A类析构函数!
请按任意键继续. . .

继承与组合混搭的构造和析构

#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
using namespace std;

class D {
public:
	D() {
		cout << "D类构造函数!" << endl;
	}
	~D() {
		cout << "D类析构函数!" << endl;
	}
};
class A {
public:
	A() {
		cout << "A类构造函数!" << endl;
	}
	~A() {
		cout << "A类析构函数!" << endl;
	}
};
class B : public A {
public:
	B() {
		cout << "B类构造函数!" << endl;
	}
	~B() {
		cout << "B类析构函数!" << endl;
	}
};
class C : public B {
public:
	C() {
		cout << "C类构造函数!" << endl;
	}
	~C() {
		cout << "C类析构函数!" << endl;
	}
public:
	D c;
};
void test() {
	C c;
}
int main()
{
	test();
	
	return 0;
}

输出:

A类构造函数!
B类构造函数!
D类构造函数!
C类构造函数!
C类析构函数!
D类析构函数!
B类析构函数!
A类析构函数!

3.为什么用成员初始化列表会快一些?

使用成员初始化列表而不是在构造函数内部逐个赋值,可以提高构造函数的执行效率。以下是使用成员初始化列表的几个好处:

1.避免多次复制:在构造函数内部逐个赋值时,如果对象有多个成员变量,可能会导致多次复制操作。而使用成员初始化列表,可以一次性将所有成员变量初始化为原始值,避免了多次复制的开销。

2.提高效率:使用成员初始化列表可以避免在构造函数内部进行逐个赋值时需要进行额外的计算和转换操作。成员初始化列表允许在编译时进行类型检查,并且可以将成员变量直接初始化为原始值,不需要进行额外的计算。

3.确保正确性:使用成员初始化列表可以确保成员变量的正确初始化顺序。成员初始化列表中的初始化顺序与类中成员变量的声明顺序一致,这可以避免在构造函数内部忘记初始化某个成员变量或初始化顺序不正确的问题。

总的来说,使用成员初始化列表可以提高构造函数的执行效率,并确保成员变量的正确初始化。但是,对于某些类型的成员变量(例如引用类型或无法进行拷贝构造的类型),使用成员初始化列表可能会导致问题,因此需要根据具体情况进行权衡。

标签:初始化,int,成员,列表,MyClass,构造函数
From: https://www.cnblogs.com/codemagiciant/p/17527268.html

相关文章

  • 40.什么情况下会调用拷贝构造函数
    40.什么情况下会调用拷贝构造函数用类的一个实例化对象去初始化另一个对象的时候函数的参数是类的对象时(非引用传递)函数的返回值是函数体内局部对象的类的对象时,此时虽然发生(NamedreturnValue优化)NRV优化,但是由于返回方式是值传递,所以会在返回值的地方调用拷贝构造函数......
  • 29.初始化和赋值的区别
    在C++中,初始化和赋值是两个不同的概念。  需要注意的是,对于某些类型的变量,初始化和赋值的效果是一样的。例如,对于基本类型的变量,使用等号进行初始化和赋值的效果是一样的。但是对于一些复杂类型的变量,如类对象,初始化和赋值的效果是不同的。在这种情况下,初始化会调用类的构造函......
  • 28.拷贝初始化和直接初始化
    ●当用于类类型对象时,初始化的拷贝形式和直接形式有所不同:直接初始化直接调用与实参匹配的构造函数,拷贝初始化总是调用拷贝构造函数。拷贝初始化首先使用指定构造函数创建一个临时对象,然后用拷贝构造函数将那个临时对象拷贝到正在创建的对象。举例如下stringstr1("Iamastring......
  • 34.C++有哪几种的构造函数
    34.C++有哪几种的构造函数C++中的构造函数可以分为4类:默认构造函数:在没有显式定义构造函数时,C++会自动生成一个默认构造函数,该函数没有参数,不执行任何操作。初始化构造函数(有参数)拷贝构造函数:当使用现有对象初始化新对象时,拷贝构造函数被调用。它的语法是在函数声明时使用一......
  • 《深入探索C++对象模型》- 第二章 - 构造函数语义学 - 笔记
    PDF版本https://www.aliyundrive.com/s/oQJJiJfQmU2......
  • Oracle-控制文件成员
    为保证数据库安全,防止因为控制文件损坏而造成实例崩溃CRASH,增加一个控制文件成员,并存放于不同于当前的ASM磁盘上,以备不时之需。1.增加一组控制文件参数[RAC01]注:第2个控制文件只需要指定到其他ASM磁盘组,+DATA为原控制文件所在ASM磁盘组。SQL>setlines999pages999showparam......
  • 如何把本地项目初始化到gitLab上去,干货分享!!
    说明:1.适用范围(高手请忽略)例如:你本地已经有一个项目了(或者别人发一个项目给你),但是你需要把这个项目托管到你的gitLab上去操作步骤:1.首先在你的gitLab上建一个空的工程目录(很简单,百度一下),建好之后看到应该是这个样子的,上面也有对应的使用说明,教你如何把本地项目上传文件到git......
  • Java中Map初始化时直接赋值的方法
    publicstaticfinalMap<String,String>BANK_TYPE=newHashMap<String,String>(){undefinedprivatestaticfinallongserialVersionUID=1L;//可有可无{undefinedput("ZX","中信银行");put("PN",&qu......
  • 将MembershipCreateStatus枚举成员翻译成自定义信息
    publicstaticclassAccountValidation{publicstaticstringErrorCodeToString(MembershipCreateStatuscreateStatus){switch(createStatus){caseMembershipCreateStatus.DuplicateUserName:......
  • Eplan API -初始化
    EplanAPI-初始化Eplan支持的开发方式一共有3种脚本dll文件形式exe离线程式形式虽然eplan二次开发也支持vb语言,但这里只讨论c#脚本(script)Eplan脚本支持的功能有限,有限的原因在于其支持的程序集有限c#中的System;System.XML;System.Drawing;System.Windows.FormsEp......