Effective cpp(1)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18218335/article/details/84504747

声明式(declaration)是告诉编译器某个东西的名称或类型,但略去细节:

extern int x; // 对象声明式

std::size_t numDigits(int number); //函数声明式

class Widget; // 类声明式

template<typename T> // 模板(template)声明式

定义式(definiton)的任务是提供编译器一些声明式所遗漏的细节。

对对象而言,定义式是编译器为此对象拨发内存的起点

对function 或function template ,定义式提供了代码本体。

对class 或 class template ,定义式列出它们的成员。

初始化(initialization)是“给予对象初值”的过程。对用户自定义对象---构造函数---默认构造函数(没有参数,或者每个参数都有缺省值)

被声明为explicit 的构造函数通常比其non-explici 兄弟更受欢迎,因为它们禁止编译器执行非预期(往往也不被期望)的类型转换

这里就有一个建议,在没有必要的时候,将其写的严格一些,声明为explicit ,禁止隐式类型转换。此时如下代码将不再合法:

class B{
public:
    explicit B(int x);
};

show_B(B& BOb);

show_B(B(1));// 合法
show_B(1);// 不合法

拷贝构造函数,拷贝赋值函数

class Widget{
public:
    Widget();                            // 默认构造函数
    Widget(const Widget & rhs);          // 拷贝构造函数
    Widget& operator = (const Widget& rhs); // 拷贝赋值操作符
    //...
};
    Widget w1;         // 调用默认的构造函数
    Widget w2(w1);     // 调用拷贝构造函数
    w1 = w2;            // 调用拷贝赋值操作符
    Widget w3 = w2;     // 调用的是:拷贝构造函数。因为,这里有构造操作,单纯的赋值操作才会引发拷贝赋值操作符

拷贝构造函数是一个尤为重要的函数,因为它定义一个对象如何值传递

    bool hasAcceptableQuality(Widget w);//
    //...
    Widget aWidget;
    if (hasAcceptableQuality(aWidget)) {
        //参数 aWidget 以值传递给hasAcceptableQuality ,上述调用中aWidget 被复制到w 内,触发拷贝构造函数
    }

值传递不是一个好办法(内存开销,隐式的拷贝构造函数产生的时间开销,容易出bug 等等),const 引用才是稳妥,高效,错误少的办法。

STL 中的很多功能以函数对象(function object)实现,那是“行为像函数”的对象,这样的对象来自于,重载了operator(),即(function call 函数调用)的类。下面我写个小例子:

class Mul
	{
	public:
		Mul() {}
		int operator()(int b) {
			return b * 2;
		}
	};
	Mul a;
	cout << a(2) << endl;

 不明确(未定义)行为的结果是不可预期的,如下:应该尽量的避免:

	int *p = 0;			// p 是一个null 指针
	std::cout << *p;	// 对一个null 指针取值,行为不明确

	char name[] = "Darla";	// 大小为6,最后的null
	char c = name[10];		// 指针指向一个无效的数组索引
							// 行为不明确
	cout << sizeof(name) << endl;

TR1:一份规范,描述加入C++ 标准程序库的诸多新机能。。。。。我举不出例子来暂时

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

条款1:View C++ as a federation of language

C++ 是一个多重范型语言(multiparadigm programing language),同时支持过程形式(procedural),面向对象(object-oriented)、函数形式(functional)、泛型形式(generic)、元编程形式(metaprogramming)的语言。这些能力和弹性使C++ 成为一个无可匹敌的工具,但也可能引发某些迷惑:所有“适当”用法似乎都有例外,如何做?

将C++ 视为一个由相关语言组成的联邦而非单一语言。但其某个次语言中,各种守则与通例都倾向简单、直观易懂、容易记住。然而,当从一个次语言转移到另一个次语言,守则可能会变:四个次语言:

1. C。C++ 以C 为基础,区块(blocks)、语句(statements)、预处理器(processor)、内置数据类型(build-in data types)、数组(arrays)、指针(pointers)等统统来自C。

2.面向对象C++。通常的C with Classes 诉求的:类(包括构造和析构),封装(encapsulation)、继承(inheritance)、多态(polymorphism)、virtual 函数(动态绑定)等等。就是通常的面向对象设计

3. Template C++。C++ 的范型编程(generic programming)部分,它功能强大,带来的崭新的编程范型(programming paradigm),就是所谓的template meta programming(TMP,模板元编程)。

4. STL。STL 是一个template 程序库。它对容器、迭代器、算法以及函数对象(containers、iterators 、algorithm)以及函数对象(function objects)的规约有极佳的紧密配合与协调,然而template 及程序库也可以其他想法建设。使用STL 必须遵循其规则。

C++ 并不是一个带有一组守则的一体语言;它从四个次语言组成的联邦政府,每个次语言都有自己的规约。记住这四个次语言会发现C++ 容易了解的多。

# 尽量以const,enum,inline 替换#define

## #define 的缺点

### #define 是在预编译的时候,就被替换了,不会进入到符号表,此时,如果编译出错,很难定位

- 举例

    - #define ASPECT_RATIO 1.653

    - 编译器报告1.653 相关的错误时,比较难定位

    - 另外,#define是简单的替换,也会多占内存

- 替换方法

    - const double AspectRatio = 1.653;

### #define 没有作用域的概念,只要定义了,就会存在,无法定义class 专属常量

- 举例

    - 略

- 替换方法

    - const 和 enum 都有作用域的概念

### 实现宏,有时有歧义

- 举例

    - #define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b))

    - CALL_WITH_MAX(++a,b);// 当a + 1 > b ,a被累加两次

- 替换方法

    - template<typename T>

inline void callWithMax(const T&a,const T&b)

{f(a > b ? a : b)}

## const 替换#define 的主要分类

### 常量指针

- 注意事项

    - 将指针声明为const

    - 如果是字符串指针,使用const char* const

    - 当然,当是字符串,我们可以使用string 类

### class 类专属常量

- 注意点

    - 初始化

        - 当使用const ,需要使用static,防止浪费内存

            - 编译器支持类内初始化

                - 直接类内声明时初始化

                - 类外定义不需初值

            - 编译器不支持类内初始化

                - 类内声明

                - 类外定义时赋初值

        - 当使用enum,仅仅可代表整型

            - 不需要考虑初始化,编译时就存在,不可取地址、引用

## 总结

### 对于单纯的常量,最好以const 对象或enum 替换#define

### 对于形似函数的宏,注意,这里说的是形似函数,有很多宏功能是无法用inline 替换的,最好改用inline 函数

猜你喜欢

转载自blog.csdn.net/qq_18218335/article/details/84504747