初始化C++类成员和在你的MFC应用中加入位置栏

原创 2002年07月22日 10:01:00

初始化C++类成员和在你的MFC应用中加入位置栏

Paul DiLascia

问题 

我的问题是关于初始化C++类成员的。我见过许多这样的代码(包括在你的栏目中也见到过):

CSomeClass::CSomeClass()

{

    x=0;

    y=1;

}

而在别的什么地方则写成下面的样子:

CSomeClass::CSomeClass() : x(0), y(1)

{

}

我的一些程序员朋友说第二种方法比较好,但他们都不知道为什么是这样。你能告诉我这两种类成员初始化方法的区别吗?

回答

从技术上说,你的程序员朋友是对的,但是在大多数情况下,两者实际上没有区别。有两个原因使得我们选择第二种语法,它被称为成员初始化列表:一个原因是必须的,另一个只是出于效率考虑。

让我们先看一下第一个原因——必要性。设想你有一个类成员,它本身是一个类或者结构,而且只有一个带一个参数的构造函数。

class CMember {

public:

    CMember(int x) { ... }

};

因为Cmember有一个显式声明的构造函数,编译器不产生一个缺省构造函数(不带参数),所以没有一个整数就无法创建Cmember的一个实例。

CMember* pm = new CMember;        // Error!!

CMember* pm = new CMember(2);     // OK

如果Cmember是另一个类的成员,你怎样初始化它呢?你必须使用成员初始化列表。

class CMyClass {

    CMember m_member;

public:

    CMyClass();

};

//必须使用成员初始化列表

CMyClass::CMyClass() : m_member(2)

{

•••

}

没有其它办法将参数传递给m_member,如果成员是一个常量对象或者引用也是一样。根据C++的规则,常量对象和引用不能被赋值,它们只能被初始化。

第二个原因是出于效率考虑,当成员类具有一个缺省的构造函数和一个赋值操作符时。MFC的Cstring提供了一个完美的例子。假定你有一个类CmyClass具有一个Cstring类型的成员m_str,你想把它初始化为"yada yada."。你有两种选择:

CMyClass::CMyClass() {

    // 使用赋值操作符

    // CString::operator=(LPCTSTR);

    m_str = _T("yada yada");

}

//使用类成员列表

// and constructor CString::CString(LPCTSTR)

CMyClass::CMyClass() : m_str(_T("yada yada"))

{

}

在它们之间有什么不同吗?是的。编译器总是确保所有成员对象在构造函数体执行之前初始化,因此在第一个例子中编译的代码将调用CString::Cstring来初始化m_str,这在控制到达赋值语句前完成。在第二个例子中编译器产生一个对CString:: CString(LPCTSTR)的调用并将"yada yada"传递给这个函数。结果是在第一个例子中调用了两个Cstring函数(构造函数和赋值操作符),而在第二个例子中只调用了一个函数。在Cstring的例子里这是无所谓的,因为缺省构造函数是内联的,Cstring只是在需要时为字符串分配内存(即,当你实际赋值时)。但是,一般而言,重复的函数调用是浪费资源的,尤其是当构造函数和赋值操作符分配内存的时候。在一些大的类里面,你可能拥有一个构造函数和一个赋值操作符都要调用同一个负责分配大量内存空间的Init函数。在这种情况下,你必须使用初始化列表,以避免不要的分配两次内存。在内部类型如ints或者longs或者其它没有构造函数的类型下,在初始化列表和在构造函数体内赋值这两种方法没有性能上的差别。不管用那一种方法,都只会有一次赋值发生。有些程序员说你应该总是用初始化列表以保持良好习惯,但我从没有发现根据需要在这两种方法之间转换有什么困难。在编程风格上,我倾向于在主体中使用赋值,因为有更多的空间用来格式化和添加注释,你可以写出这样的语句:x=y=z=0;

或者memset(this,0,sizeof(this));

注意第二个片断绝对是非面向对象的。

当我考虑初始化列表的问题时,有一个奇怪的特性我应该警告你,它是关于C++初始化类成员的,它们是按照声明的顺序初始化的,而不是按照出现在初始化列表中的顺序。

class CMyClass {

    CMyClass(int x, int y);

    int m_x;

    int m_y;

};

CMyClass::CMyClass(int i) : m_y(i), m_x(m_y)

{

}

你可能以为上面的代码将会首先做m_y=I,然后做m_x=m_y,最后它们有相同的值。但是编译器先初始化m_x,然后是m_y,,因为它们是按这样的顺序声明的。结果是m_x将有一个不可预测的值。我的例子设计来说明这一点,然而这种bug会更加自然的出现。有两种方法避免它,一个是总是按照你希望它们被初始化的顺序声明成员,第二个是,如果你决定使用初始化列表,总是按照它们声明的顺序罗列这些成员。这将有助于消除混淆。

初始化C++类成员和在你的MFC应用中加入位置栏

2000年12月09日 03:04:00 Paul DiLascia问题 我的问题是关于初始化C++类成员的。我见过许多这样的代码(包括在你的栏目中也见到过):CSomeClass::CS...
  • softart
  • softart
  • 2007年10月27日 07:44
  • 184

初始化C++类成员和在你的MFC应用中加入位置栏

 Paul DiLascia问题  我的问题是关于初始化C++类成员的。我见过许多这样的代码(包括在你的栏目中也见到过):CSomeClass::CSomeClass(){    x=0;    y=...
  • ghj1976
  • ghj1976
  • 2000年12月09日 03:04
  • 1127

初始化C++类成员和在你的MFC应用中的加入位置

问题  我的问题是关于初始化C++类成员的。我见过许多这样的代码(包括在你的栏目中也见到过):CSomeClass::CSomeClass(){    x=0;    y=1;}而在别的什么地方则写成...
  • Jans
  • Jans
  • 2001年07月01日 17:50
  • 1000

C++类成员变量初始化位置

static: static表示的是静态的。类的静态成员函数、静态成员变量是和类相关的,而不是和类的具体对象相关的。即使没有具体对象,也能调用类的静态成员函数和成员变量。一般类的静态函数几乎...
  • st125475466
  • st125475466
  • 2015年09月08日 11:29
  • 915

你的MFC应用中加入位置栏

问题我刚刚在几台机器上安装了Windows® 2000 Release Candidate 1,不知道怎样在我的MFC应用中得到具有新的Outlook风格栏目的Open对话框(见图1)。 Figure...
  • No9
  • No9
  • 2002年07月22日 10:01
  • 942

c++类中对数据成员进行初始化和赋值的区别

在c++中定义一个类 ,对于构造函数 我们经常是这么写的: class test { public: test(int n_x , int n_y) { x ...
  • zengchenacmer
  • zengchenacmer
  • 2014年05月14日 11:05
  • 2079

C++类构造函数初始化列表及初始化成员变量的误区

构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。例如: class CExample { public: int a; f...
  • sinat_20265495
  • sinat_20265495
  • 2016年12月14日 20:13
  • 1806

C++类中的数据成员能否在定义类的时候就初始化?

class A{ private: int a=1; }; 即上述关于类的定义正确与否?一般而言,类中的数据成员在定义类的时候是不能初始化的。这是一个可以值得探讨的话题,每个人的解释都不...
  • Tsinting
  • Tsinting
  • 2017年03月06日 17:31
  • 2246

C++ - 类的成员变量 声明顺序 与 初始化顺序 相同

类的成员变量 声明顺序 与 初始化顺序 相同 本文地址: http://blog.csdn.net/caroline_wendy/article/details/23845027 类成员的默认...
  • u012515223
  • u012515223
  • 2014年04月16日 14:40
  • 2913

c++类中成员变量的初始化总结

关于这个问题是引起来源于一则面试问题:引用型成员变量如何初始化?回答的不是很确定,于是对这个问题研究一下。 1、普通的变量:一般不考虑啥效率的情况下 可以在构造函数中进行赋值。考虑一下效率的可以再构造...
  • jenghau
  • jenghau
  • 2009年10月31日 22:30
  • 9396
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:初始化C++类成员和在你的MFC应用中加入位置栏
举报原因:
原因补充:

(最多只允许输入30个字)