沐枫小筑(C++)

爱老婆,要比编程多一点...

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  18 Posts :: 0 Stories :: 84 Comments :: 0 Trackbacks

公告

沐枫的个人主页

eoool.com生成

eoool.com生成

常用链接

留言簿(8)

我参与的团队

搜索

  •  

积分与排名

  • 积分 - 56026
  • 排名 - 397

最新评论

阅读排行榜

评论排行榜

   C语言确实很优雅,整个语言的设计简洁一致。而在C++中,有一个让人诟病的问题就是变量初始化的不一致性。
   C语言中的初始化,都是用花括号进行,简单美观:

int array[] = {1,2,3,4,5};
struct Point point = {23};
struct Point arrPoint[] = 
{
  {
2,3},
  {
4,5},
  {
6,7}
};

   C++自然也兼容了C语言的初始化机制。然而,C++的Class乃至STL都不支持。它们要用不同的方式来初始化, 甚至根本不能够直接初始化, 只能使用运行时的赋值。
   比如Class:
class Param
{
public:
  
int Age;
  
int Value;
private:
  
int Level;
};

Param param 
= {2,3}; // ERROR
Param param = {2,3,4}; //ERROR
   无法初始化。而如果不初始化的话,所有的成员而处于无政府状态,这显然很不让人放心。于是,C++提供了专门用于Class的初始化方式--构造函数:
class Param
{
public:
  Param(
int x, int y)
    : x_(x), y_(y)
  {}
  Param()
    : x_(
0), y_(0)
  {}
private:
  
int x_, y_;
};

Param param(
1,2);
//
Param param;
   有了构造函数,可以在构造函数的初始化列表中对成员进行初始化。可是很明显,这里头还是有一个陷阱,默认构造初始化和非默认构造初始化的调用方式是不一致的。默认构造函数不能用括号来调用,否则编译器将会发疯:
Param param();
   它会把上面的语句看成是函数声明,而后面调用的时候就会出错,而错误信息可能会让你抓狂一下。但是这样也就算了,偏偏 new 可以接受有括号和没括号两种写法:
Param* p1 = new Param;
Param
* p2 = new Param();
   再来说说初始化列表。初始化列表,事实上,也只能支持简单的标量类型,诸如int,bool,指针之类的;复杂点的,如数组、结构,不好意思,不支持--只能在构造函数体中进行赋值。还有一个很迷糊初学者的问题是,成员初始化的顺序仅依赖于成员定义的顺序,而不是初始化列表中的顺序。

   再比如STL容器,这下好象更惨,连构造函数都帮不上忙了,除了初始化一个空的容器,或是复制一下别的容器,我们只能做用默认构造函数进行初始化。我们拿数组和vecotr做个比较:
// 数组
int arr[]={1,2,3,4};
// vector
vector<int> iarr;
// 必须在某个函数中赋初值
void init()
{
  
for(int i = 1; i <= 4++i) 
    iarr.push_back(i);
}

   再复杂一点的数据结构,那单单赋值程序就要写上老长,而且还不好看。还要记得调用。这对于仅仅是简单的设置一些初值的用途来说,太过于烦琐。

   横向比较,这次好象C++还不会太落伍,只有C和动态语言提供了初始化特性,其它支持OO高级语言好象都是学C++的。如Java, C#(注C#3.0开始提供初始化功能)...
   
   C++能不能做到简洁一致的实始化呢?
   Boost的assign库做了许多有益的工作。使用assign库,至少现在可以初始化了:
vector<int> arr = list_of(1)(2)(3)(4);   

typedef boost::tuple
<int,std::string,int> tuple;
vector
<tuple> v = tuple_list_of( 1"foo"2 )( 3"bar"4 );

map
<int,int> next = map_list_of(1,2)(2,3)(3,4)(4,5)(5,6);

stack
<string> names = list_of( "Mr. Foo" )( "Mr. Bar")( "Mrs. FooBar" ).to_adapter();
   如果是赋值,也可以简略很多:
vector<int> v;
+= 1,2,3,repeat(10,4),5,6,7,8,9;
// v = [1,2,3,4,4,4,4,4,4,4,4,4,4,5,6,7,8,9]
  不过,也仅能如此了。assign经过许多努力,也仅能支持容器的初始化,而且还不够漂亮。

   C++0x已确定提供与C一致的初始化功能。 Initialer lists Initializer Lists for Standard Containers Initializer lists WP wording 等草案就是为了这个目的服务的。
   如果使用C++0x,那么程序的初始化将变得清晰和一致:
complex<double> z = {1,2}; 
//
complex<double> z {1,2}; 
// 初始化中,有等号和无等号都是允许的,下同。
+= {2,3};

int a = {1}; 

new vector<string>{"once""upon""a""time"}; 

f( {
"Nicholas""Annemarie"} ); // 参数是两个元素的列表

return { "Norah" }; // 返回只有一个元素的列表
 
int* e {};  // 初始化为0或NULL指针

map
<string,int> anim = 

  {
"bear",4}, 
  {
"cassovary",2}, 
  {
"tiger",7
}; 

   这好象是C++欠了十多年的债吧。
   
posted on 2007-09-27 17:39 沐枫 阅读(2657) 评论(6)  编辑 收藏 引用 所属分类: C++

Feedback

# re: 从赋值到初始化 2007-09-27 20:37 爱子
QQ群名称:游戏编程学习和开发M
QQ群号码:43047318
创建人QQ号码:光爱之子(273612158)
QQ群描述:群里是可以提供游戏和有关游戏编程知识。同时还有数据结构学习。 和一些懂得操作系统原理的人 希望你加入。 谢谢!还有游戏策划,运营有关方面知识。   回复  更多评论
  

# re: 从赋值到初始化 2007-09-28 00:15 lovedday
C++,拙劣的设计,D语言正式出来后我估计就不想用C++了。  回复  更多评论
  

# re: 从赋值到初始化 2007-09-28 14:09 shen126
呵呵,很喜欢楼主的选题和风格.
Thanks!  回复  更多评论
  

# re: 从赋值到初始化 2007-09-30 14:08 空明流转
我还真不觉得这样有什么好。。。只是现在用C#,觉得C++不支持构造函数的多态行为是一件多么让人感到麻烦的事情。  回复  更多评论
  

# re: 从赋值到初始化 2007-10-04 16:21 chenjh
楼主你好,你对C++真是了解,不知你能否帮我解说下我手上的程序,是用C++编写的关于伪彩色处理的,不知可否?谢谢!

  回复  更多评论
  

# re: 从赋值到初始化 2007-10-06 23:10 沐枫
@空明流转
我也用C#的啊?可是怎么不知道c#居然有构造函数多态行为。
你可能是指从一个构造函数调用另一个构造函数吧。
C++将会在下一个标准中增加这个功能。  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理