Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6275991
  • 博文数量: 2759
  • 博客积分: 1021
  • 博客等级: 中士
  • 技术积分: 4091
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-11 14:14
文章分类

全部博文(2759)

文章存档

2019年(1)

2017年(84)

2016年(196)

2015年(204)

2014年(636)

2013年(1176)

2012年(463)

分类: C/C++

2013-11-14 11:33:51

原文地址:effective C++学习总结 作者:hustfxj

让自己习惯C++

1、 Classes的构造函数都被声明为explict,这可以阻止它们被用来执行隐式类型转换。

2、 尽量以constenuminline替换#define

3、 const注意的地方

char* p="hello";  //non-const pointer,non_const data

const char* p1="hello";  //non-const pointer,const data

char* const p2="hello";  //const pointer,non_const data

STL迭代器以指针为根据塑造,所以迭代器的作用就像个T*指针。说明迭代器为const就像声明指针为const一样(即声明一个T* const),表示这个迭代器不得志向其他不同的东西。

const std::vector::iterator=vec.begin();  //iter相当于T* const

std::vector::const_iterator=vec.begin();  //iter相当于const T*

4、 const成员函数

mutable //修饰的成员变量将可以在const成员函数更改

一般针对一个函数可以写两个函数:const函数和non-const函数,这样往往会造型代码空间的浪费。怎么做才能使不浪费呢?下面举例说明

Before

const char& operator [](std::size_t position) const           //const成员函数

{

//边界检测

//数据访问

}

char& operator [](std::size_t position)                         //non-const成员函数

{

//边界检测

//数据访问

}

After

const char& operator [](std::size_t position) const           //const成员函数

{

//边界检测

//数据访问

}

char& operator [](std::size_t position)                         //non-const成员函数

{

    Return const_cast(static_cast(*this)[position])

}

5、 确定对象被使用前已被初始化

n  为内置对象进行手工初始化,因为C++不保证初始化它们。

n  构造函数最好使用成员初始化列表(member initialization list),而不要在构造函数本体内使用赋值操作(为了效率)。初始化列表列出的成员变量,其排列次序应该和它们在class中的声明次序相同。

n  为免除“跨编译单元的初始化次序”问题,请以local static对象替换non-local static对象。

构造/析构/赋值运算

6、 若不想使用编译器自动生成的函数,就该明确拒绝

为驳回编译器自动(暗自)提供的机能,可将相应的成员函数声明为private并且不予实现。

7、 为多态基类声明virtual析构函数

8、 别让异常逃离析构函数(这一点自己可能不太理解

9、 在构造和析构期间不要调用virtual函数,因为这类调用从不下降至derived class

11、在处理operater=中处理“自我赋值”问题上要小心

12、复制对象时勿忘其每一个成分

n  这里尤其注意赋值derived class时保证所有base class成分

注意:下面copy函数不能调用copy assignmentcopy assignment不能调用copy 函数。只能是相互匹配的运用这两种copy函数。如下

Derived& Derived::operator=(const Derived& rhs)

{

  if (this == &rhs) return *this;

  Base::operator=(rhs);    //  调用 this->Base::operator=

  y = rhs.y;

  return *this;

}

Derived& Derived::operator=(const Derived& rhs)

{

  if (this == &rhs) return *this;     //  *this Base 部分

  static_cast(*this) = rhs;    //  调用 operator=                                    

  y = rhs.y;

  return *this;

}

Derived(const Derived& rhs): Base(rhs), y(rhs.y)

{

}

资源管理

13、为了防止资源泄漏,请使用RAII对象。两个常用的RAII Class分别是tr1:shared_ptrauto_ptr。前者通过是较佳选择,因为其copy行为比较直观。若选择auto_ptr复制对象会使它变成null

17、以独立语句将newed对象存储于智能指针内。如果不这样做,一旦异常被抛出,容易资源泄漏

设计与声明

18、让接口容易被正确使用,不易被误用

n  好的接口很容易正确使用,不容易被误用。你应该在你的所有接口中努力达成这些性质

n  “促进正确使用”的办法包括接口的一致性,以及与内置类型的行为兼容

n  “阻止误用”的办法包括建立新类型,限制类型上的操作,束缚对象值,以及消除客户的资源管理责任

 trl::shared_ptr支持定制删除(custom deleter)。这可防范DLL问题,可被用来自动解除互斥锁(mutexes)等等

19设计class犹如设计type(设计class需要知道的几个问题)

20、宁以pass-by-reference-to-const替换pass-by-value

但要注意:这个规则并不适用于内置类型,以及STL的迭代器和函数对象。对她们而言,pass-by-value往往比较适当。

同时当函数必须返回对象时,别妄想返回其reference

24若所有参数皆需类型转换,请为此采用non-member函数

意思:如果你需要为某个函数的所有参数进行类型转换(包括this指针所指的那个隐喻参数),那么这个函数必须是个non-member

25考虑写一个不抛出异常的swap函数(这个很重要,可以仔细看看)

实现

27、尽量少做转型动作

   Const_cast:常量性转除转换

   Dynamic_cast: 安全向下转换

   Reinterpret_cast: 强制性

   Static_cast

模板与泛型

42、了解typenameclass区别

43、处理模板化基类的名称(函数、成员……)

45、使用成员函数版本生成“可接受所有兼容类型”

46、需要类型转换时请为模板定义非成员函数

47、请使用traits_calsses表示类型信息

定制newdelete

49了解new-handler的行为

50、了解newdelete的合理替换时机

51、主要还是将了operator newoperator delete重载问题

注意: 当你写一个placement operator new,请确定出写出了对应的placement operator delete

      当你声明placement newplacement delete ,请确定不要无意识地遮掩了他们的正常版本

杂项讨论

Str1:(新增加的组件)

随机数   http://sysuca.blog.163.com/blog/static/111082202200921475655472/

正则表达(另外boost这种准标准库也带有正则表达)


Boost:

这个准标准库,很重要,包含了正则表达、动态数组等

阅读(557) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~