Effective C++_笔记_条款00_基本术语
2014-05-06 23:26
190 查看
(整理自Effctive C++,转载请注明。整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/)
下面是每一位C++程序员都应该了解的C++词汇。
所谓声明式(declaration)是指定某个东西的名称和类型,但略去细节。就是通知编译器这有一个与这个名字相关的东西,并且它是这个类型的。例如:
注意:作者将内置类型的变量和用户自定义类型的的变量都视为对象。
所谓定义式(definition)的任务是提供编译器一些声明式所遗漏的细节。对于对象而言定义是编译器为对象分配内存的地点。对函数或函数模版而言, 定义式提供了代码的本体。对于类或者类模版而言,定义式列出它们的成员。例如:
[/code]
[/code]
被声明为explicit的构造函数比no-explicit更受欢迎,因为它们禁止编译器执行非预期的类型转换。除非有非常明确的理由允许构造函数被用于隐式类型转换,否则应声明为explicit。
[/code]
copy构造函数和copy赋值操作符很容易区别:如果一个新对象被定义,一定会有个构造函数被调用,不可能调用赋值操作。如果没有新对象被定义,就没有构造函数被调用,那么当然就是赋值操作被调用。
[/code]
这个声明创建了一个名叫a的指针变量,后面那条语句把12存储在a所指向的内存位置。我们在声明指针时没有给它初始化,所以我们无法预测12这个值会存储在什么地方。所以如果程序执行这个赋值操作,会发生什么情况呢?如果你运气好,a的初始值会是个非法地址,这样的赋值语句就会出错,从而终止程序;一个更为严重的情况是:这个指针偶尔可能包含了一个合法的地址。那么那个位置的值就会被修改,虽然你并无意去修改它。像这种类型的错误非常难以捕捉,因为引发错误的代码可能与原先用于操作那个值的代码完全不相关。所以,在对指针进行间接访问之前,必须对其进行初始化。同样的对NULL指针解引用,对数组越界操作,都会引发不明确行为。
下面是每一位C++程序员都应该了解的C++词汇。
1C++中 声明和定义 的区别
注意:关于声明和定义的区别,我查了一些资料,和本书也有不一致的地方。暂且按照本书,欢迎指正!。所谓声明式(declaration)是指定某个东西的名称和类型,但略去细节。就是通知编译器这有一个与这个名字相关的东西,并且它是这个类型的。例如:
extern int x ;//对象(object)声明
std::size_t numDigits(int number) ; //函数声明
class Wjdget ;//类的声明
template<typename T>
class GraphNode ; //模版声明
注意:作者将内置类型的变量和用户自定义类型的的变量都视为对象。
所谓定义式(definition)的任务是提供编译器一些声明式所遗漏的细节。对于对象而言定义是编译器为对象分配内存的地点。对函数或函数模版而言, 定义式提供了代码的本体。对于类或者类模版而言,定义式列出它们的成员。例如:
[code] int x ; //对象的定义
std::size_t numDigits(int number)//函数的定义式
{//次函数返回的是整数数字的位数
std::size_t digitsSoFar = 1 ;
while((number/=10)!=0) ++digitsSoFar ;
return digitsSoFar ;
}
class Widget//class的定义式
{
public:
Widget() ;
~Widget() ;
...
};
template<typename T> //模版的定义式
class GraphNode
{
public:
GraphNode() ;
~GraphNode() ;
...
};
[/code]
2关于构造函数
2.1 默认构造函数和explicit声明
对用户自定义的类型的对象而言,初始化由构造函数执行。default构造函数是一个可被调用而不带任何实参者。这样的构造函数要不没有参数,要不就是每个参数都有缺省值。构造函数被声明为explicit,这可以阻止它们被用来执行隐式的类型转换(implicit type conversions),但仍可被用来就行显示的类型转换(explicit type conversions) :[code] class B
{
public:
explicit B(int x = 0 , bool b = true ); //default构造函数
};
void doSomething (B bObject) ; //函数,接受一个B类型的对象
B bObject1 ;//一个类型为B的对象
doSomething (bObject1) ; //没问题,传递一个B类对象
B bObject2(28) ;//没问题,根据int 28建立一个B类对象(bool参数缺省为true)
doSomething (28) ; //错误!doSomething应该接受一个B类对象,而不是int,而int和B之间没有隐式的类型转换
doSomething (B(28)) ; //没问题,使用B的构造函数将int显示转换为一个B类对象,从而调用合法
[/code]
被声明为explicit的构造函数比no-explicit更受欢迎,因为它们禁止编译器执行非预期的类型转换。除非有非常明确的理由允许构造函数被用于隐式类型转换,否则应声明为explicit。
2.2 copy构造函数和copy赋值操作符
copy构造函数被用来“以同型对象初始化自我对象”,copy赋值操作符被用来“从另一个同型对象拷贝其值到自我对象”。例如:[code] class Widget
{
public:
Widget();//default构造函数
Widget(const Widget& rhs );//copy构造函数
Widget& operator= (const Widget& rhs);//copy赋值操作符
...
};
Widget w1 ;//调用default构造函数
Widget w2(w1);//调用copy构造函数
w1 = w2 ; //调用copy赋值操作符
Widget w3 = w2 ;//调用copy构造函数
[/code]
copy构造函数和copy赋值操作符很容易区别:如果一个新对象被定义,一定会有个构造函数被调用,不可能调用赋值操作。如果没有新对象被定义,就没有构造函数被调用,那么当然就是赋值操作被调用。
3 不明确行为
由于各种因素,有些C++的行为没有定义:你无法稳定预估运行期会发生什么事。看如下代码:[code] int* a ;
*a = 12 ;
[/code]
这个声明创建了一个名叫a的指针变量,后面那条语句把12存储在a所指向的内存位置。我们在声明指针时没有给它初始化,所以我们无法预测12这个值会存储在什么地方。所以如果程序执行这个赋值操作,会发生什么情况呢?如果你运气好,a的初始值会是个非法地址,这样的赋值语句就会出错,从而终止程序;一个更为严重的情况是:这个指针偶尔可能包含了一个合法的地址。那么那个位置的值就会被修改,虽然你并无意去修改它。像这种类型的错误非常难以捕捉,因为引发错误的代码可能与原先用于操作那个值的代码完全不相关。所以,在对指针进行间接访问之前,必须对其进行初始化。同样的对NULL指针解引用,对数组越界操作,都会引发不明确行为。
相关文章推荐
- Effective C++ 小笔记:条款7-12
- Effective C++_笔记_条款11_在operator=中处理“自我赋值”
- Linux学习笔记00:基本的快捷方式以及命令
- 【转载】【时序约束学习笔记1】Vivado入门与提高--第12讲 时序分析中的基本概念和术语
- Effective C++_笔记_条款02_尽量以const、enum、inline替换#define
- Effective C++_笔记_条款13_以对象管理资源
- Effective C++学习笔记_条款43:学习处理模板化基类内的名称
- Effective C++_笔记_条款03_尽可能使用const
- Effective C++ 55个条款 笔记
- Effective c++ 条款16学习笔记: 成对使用new和delete时要采取相同形式
- Effective C++学习笔记 条款04:确定对象被使用前已先被初始化
- Effective C++ 小笔记:条款3-6
- Effective C++ 阅读笔记_条款27 尽量少做转型动作
- Effective C++ 条款12:复制对象时勿忘其每一个成分 学习笔记
- Effective C++_笔记_条款07_为多态基类声明virtual析构函数
- 条款1:尽量用const和inline而不用#define [effective C++ 学习笔记]
- 《Effective C++ 》学习笔记-第六章 条款33:避免遮掩继承而来的名称 Avoid hiding inherited names
- Effective c++学习笔记——条款09:绝不在构造和析构过程中调用virtual函数
- 深度学习笔记之一些基本术语
- 学习笔记(一):计算机体系架构的术语和基本概念