重读经典-《Effective C++》Item0:基本概念

晨曦之光 发布于 2012/03/09 14:17
阅读 184
收藏 0

本博客(http://blog.csdn.net/livelylittlefish )贴出作者(三二一@小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!

 

 

基本概念

 

1. 声明

 

Declaration:告诉编译器某个东西的名称和类型,但略去细节。

 

2. 定义

 

Definition:提供编译器一些声明所遗漏的细节。

 

对对象而言,定义是编译器为此对象分配内存的地点。

functionfunction template而言,定义提供了代码本体。

classclass template而言,定义类出他们的成员。

 

3. 初始化

 

Initialization:是给予对象初值的过程。

对用户自定义类型的对象而言,初始化由构造函数执行。

 

4. default构造函数

 

是一个可被调用而不带任何实参者,即要么没有参数,要么每个参数都有缺省值。例如:

 

class A
{
public:
    A(); //default构造函数
};

class B
{
public:
    explicit B(int x=0, bool b=true); //default构造函数
};

class C
{
public:
    explicit C(int x); //不是default构造函数
};

 

5. explicit关键字

 

构造函数被声明为explicit,如上所示,可以阻止他们被用来执行隐式类型转换(implicit type conversions),但他们仍可以被用来进行显式类型转换(explicit type conversions)

 

explicit的构造函数禁止编译器执行非预期的类型转换。

 

例如,

 

/**
 * <Effective C++>, page 5
 * difference between explicit and implicit
 * platform: visual studio 2005, win32
 * filename: item0.1.cpp
 */
#include <iostream>
using namespace std;
 
class B
{
	int mx;
	bool mb;
 
public:
	//(2) add 'explicit', then, the implicit type conversion will be disabled
	//then, an error will occur at (3)
	B(int x = 0, bool b = true): mx(x), mb(b)
	{
		cout<<"B constructor!"<<endl;
	}
 
	int getmx() const
	{
		return mx;
	}
 
	bool getmb() const
	{
		return mb;
	}
};
 
void dosomething(B obj)
{
	cout<<"dosomething called! B.mx = "<<obj.getmx()<<", B.mb = "<<obj.getmb()<<endl;
}
 
int main()
{
	B obj1;
	dosomething(obj1); //ok
 
	B obj2(28);
	dosomething(obj2); //ok
 
	dosomething(B(38)); //ok
 
	/*(3) error C2664: 'dosomething' : cannot convert parameter 1 from 'int' to 'B'
	      Constructor for class 'B' is declared 'explicit' */
	dosomething(48); //(1) ok, implicit type conversion
 
	/*(3) error C2664: 'dosomething' : cannot convert parameter 1 from 'char' to 'B'
	      Constructor for class 'B' is declared 'explicit' */
	dosomething('c'); //(1) ok, implicit type conversion, ASCII code of 'c' is 99
 
	/*(3) error C2664: 'dosomething' : cannot convert parameter 1 from 'double' to 'B'
	      Constructor for class 'B' is declared 'explicit' */
	dosomething(58.5); //(1) ok, implicit type conversion, but there is a warning
	                   /* warning C4244: 'argument' : conversion from 'double' to 'int',
	                      possible loss of data*/
 
	return 0;
} 
  

 

代码注释中的(1),(2),(3)表示step编号。

 

(1) class B的构造函数没有加上explicit关键字修饰时,

 

dosomething(48);

dosomething('c');

dosomething(58.5);

均执行了隐士类型转换,即将48等数据转换为B型对象。

 

运行结果如下:

B constructor!

dosomething called! B.mx = 0, B.mb = 1

B constructor!

dosomething called! B.mx = 28, B.mb = 1

B constructor!

dosomething called! B.mx = 38, B.mb = 1

B constructor!

dosomething called! B.mx = 48, B.mb = 1

B constructor!

dosomething called! B.mx = 99, B.mb = 1

B constructor!

dosomething called! B.mx = 58, B.mb = 1

 

此处,我们可以看出,这种隐式类型转换,只对整型数据有效。

 

(2) class B的构造函数加上explicit关键字后,intchardouble型的数据隐式转换为B型即被阻止。

 

(3) 因此,

 

dosomething(48);

dosomething('c');

dosomething(58.5);

均会出现编译错误,如不能将int类型转换为B

 

6. Copy构造函数与copy assignment操作符

 

copy构造函数用来以同型对象初始化自我对象;

Copy assignment操作符被用来从另一个同型对象中拷贝其值到自我对象。

 

例如,

 

class Widget

{

public:

    Widget();                             //default构造函数

    Widget(const Widget& rhs);            //copy构造函数

    Widget& operator=(const Widget& rhs)  //copy assignment操作符

    //...

};

 

Widget w1;            //调用default构造函数

Widget w2(w1);        //调用copy构造函数

W1 = w2;              //调用copy assignment操作符

Widget w3 = w2;       //调用copy构造函数!

 

如果一个新对象被定义,一定会有个构造函数被调用,不可能调用赋值操作,如上w1w2w3

如果没有新对象被定义,就不会有构造函数被调用,那么当然就是赋值操作被调用,如上w1=w2

 

代码如下。

 

/**
 * <Effective C++>, page 5
 * the difference between copy constructor and copy assignment operator
 * platform: visual studio 2005, win32
 * filename: item0.2.cpp
 */
#include <iostream>
using namespace std;
 
class Widget
{
public:
    Widget() //default constructor
    {
        cout<<"default constructor called!"<<endl;
    }
 
    Widget(const Widget& rhs) //copy constructor
    {
        cout<<"copy constructor called!"<<endl;
    }
 
    Widget& operator=(const Widget& rhs) //copy assignment operator
    {
        cout<<"copy assignment operator called!"<<endl;
	    return *this;
    }
 
    ~Widget()
    {
        cout<<"destructor called!"<<endl;
    }
};
 
int main()
{
    Widget w1;      //call default constructor
    Widget w2(w1);  //call copy constructor
    w1 = w2;        //call copy assignment operator
    Widget w3 = w2; //call copy constructor

    cout<<"sizeof widget = "<<sizeof(Widget)<<endl;
    cout<<"sizeof w1 = "<<sizeof(w1)<<endl;

    return 0;
}

 

运行结果如下。

default constructor called!

copy constructor called!

copy assignment operator called!

copy constructor called!

sizeof widget = 1

sizeof w1 = 1

destructor called!

destructor called!

destructor called!

 

再如,它定义一个对象如何passed by value(以值传递)

bool hasAcceptableQuality(Widget w);

//...

 

Widget aw;

if(hasAcceptableQuality(aw))

...

 

参数w是以by value的方式传递给hasAcceptableQuality,所以上述调用中aw被复制到w体内,且这个复制动作由Widgecopy构造函数完成。

 

刚才说如果有一个新的对象产生,才会调用构造函数,但此处也没有发现有新的对象产生啊,为什么会调用copy构造函数呢?

回答这个问题,我们可以想想函数的调用过程,对于函数而言,如果其不被调用,其形参是不会占用内存空间的;而一旦被调用,编译器即会在栈中为其分配空间,此处的w是个对象,不是引用也不是指针,所以当实参aw传递到w时,因为在栈中有新的对象产生,(只不过该对象的生命周期较短,函数调用结束后,栈被释放,显然该对象也不存在了),因此通过copy构造函数将实参传递给形参。

 

当然,以by value的方式传递用户自定义类型通常不是个好主意,pass-by-reference-to-const往往是较好的选择。

 

7. STL

 

STL是所谓标准模板库(Standard Template Library),是C++标准程序库的一部分,主要包括以下6中组件:

容器(container):vectorlistsetmap

迭代器(interator):vector<int>::iteratorset<string>::iterator

算法(algorithm):for_eachfindsort

仿函数(functor):行为类似函数,可以作为算法的某种策略

适配器(adapter):一种用来修饰容器,仿函数或者迭代器接口的东西

分配器(allocator):负责空间配置与管理。

 

8. TR1Boost

 

TR1(Technical Report 1)是一份规范,描述加入C++标准程序库的诸多新机能。这些技能以新的class templatesfunction templates形式体现,针对的题目有hash tables(哈希表)reference-counting(引用计数)smart pointers(智能指针)regular expressions(正则表达式)等。

 

所以TR1组件都被置于命名空间tr1中,后者嵌套于命名空间std内。

 

Boost是个组织,提供可以移植、同僚复审、源码开放的C++程序库。大多数TR1机能以Boost的工作为基础。

http://boost.org

 

注:该文程序亦可在Linux平台上运行。 

 


原文链接:http://blog.csdn.net/livelylittlefish/article/details/5728892
加载中
返回顶部
顶部