C++初始化与赋值

摘自:http://student.csdn.net/link.php?url=http://www.cnblogs.com%2Fchio%2Farchive%2F2008%2F10%2F06%2F1305145.html

C++初始化与赋值

先来个区别说明:赋值操作是在两个已经存在的对象间进行的,而初始化是要创建一个新的对象,并且其初值来源于另一个已存在的对象。编译器会区别这两种情 况,赋值的时候调用重载的赋值运算符,初始化的时候调用拷贝构造函数。如果类中没有拷贝构造函数,则编译器会提供一个默认的。这个默认的拷贝构造函数只是 简单地复制类中的每个成员。下面看例子。

c++中初始化和赋值操作差别是很大的。
对于基本数据类型差别不大:
比如:
inta=12;//initialization,copy0X000Ctoa
a=12;//assignment,copy0X000Ctoa
但是对用户自定义的数据类型比如String初始化和赋值就差别很大:
classString...{
public:
String(constchar*init);//intentionallynotexplicit!
~String();
String(constString&that);
String&operator=(constString&that);
String&operator=(constchar*str);
voidswap(String&that);
friendconstString//concatenate
operator+(constString&,constString&);
friendbooloperator<(constString&,constString&);
//...
private:
String(constchar*,constchar*);//computational
char*s_;
};
初始化的构造过程比较简单:先分配一个足够大的空间然后填充上数据:
String::String(constchar*init)...{
if(!init)init="""";
s_=newchar[strlen(init)+1];
strcpy(s_,init);
}
析构过程更简单:
String::~String()...{delete[]s_;}

但是如果赋值操作就复杂多了:
String&String::operator=(constchar*str)...{

if(!str)str="""";

char*tmp=strcpy(newchar[strlen(str)+1],str);//多了中间变量

delete[]s_; //多了删除s_;
s_=tmp; //多一个赋值操作!现在是指向字符的指针,如果是个大对象,效率的差别可想而知.

return*this;
}

C++初始化语法的不一致性:

C语言确实很优雅,整个语言的设计简洁一致。而在C++中,有一个让人诟病的问题就是变量初始化的不一致性。

C语言中的初始化,都是用花括号进行,简单美观:
int array[] = { 1 , 2 , 3 , 4 , 5 };
struct Pointpoint = { 2 , 3 };
struct PointarrPoint[] =
{
{
2 , 3 },
{
4 , 5 },
{
6 , 7 }
};

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

Paramparam
= { 2 , 3 }; // ERROR
Paramparam = { 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_;
};

Paramparam(
1 , 2 );
//
Paramparam;
有了构造函数,可以在构造函数的初始化列表中对成员进行初始化。可是很明显,这里头还是有一个陷阱,默认构造初始化和非默认构造初始化的调用方式是不一致的。默认构造函数不能用括号来调用,否则编译器将会发疯:
Paramparam();
它会把上面的语句看成是函数声明,而后面调用的时候就会出错,而错误信息可能会让你抓狂一下。但是这样也就算了,偏偏 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 );

typedefboost::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;
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 };
// 初始化中,有等号和无等号都是允许的,下同。
z += { 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 }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值