Eff C++ 笔记1
2018-06-17 21:43:10来源:未知 阅读 ()
? C++是一个语言联邦(Federation of languages)
1. C Style language
2. Object-Oriented C++
3. Template C++
4. STL/TR1/boost..
? 使用const,enum,inline代替#define
1. 使用const datatype constName = constValue 代替 #define constName constValue
比如全局常量:
const int maxN = 1000005; //代替 #define maxN 1000005
在类中,类专属常量:
class someClass{ private: static const int maxN = 1000005; int someData[maxN]; ... }
2. enum hack!
class someClass{ private: enum { maxN = 1000005 };//enum令maxN变成一个记号名称 int someData[maxN]; ... }
enum的某些特性更像#define而不是const,某些情况下更符合我们的需求。(例如取地址对于enum不合法而对const就合法)
enum hack使template metaproprogramming的基础技术。
3. 使用inline function代替宏
常见宏 #define call_with_max(a, b) foo(a > b ? a : b) 会出现大量的错误,
必须使用小括号将参数全部区别 #define call_with_max(a, b) foo((a) > (b) ? (a) : (b)) ,
即便如此在实际操作时依旧容易出错(不能扩展代码与灵活调用),应用inline function取代
template <typename T> inline void callWithMax(const T& a, const T& b){ foo(a > b ? a : b); }
? Const的妙用
1. Const声明帮助编译器侦测出错误
const指定了一个不可改动的对象,而编译器会强制的实施它。(!指出来可以获得编译器的帮助,确保其不被违反!)
这个对象可以是global或者namespace域中的常量。也可以修饰block scope中被声明为static的对象,亦可以修饰class内部的所有变量。
而对于指针,可以指出指针自身,指针所指,两者皆是,或两者皆不是Const。在*左表示指针所指是常量,在*右表示指针自身是常量,而在*两侧表示两者皆是常量。
int someValue = 12345; int* pSomeValue = someValue; // 两者皆不是常量 const int* pSomeValue = someValue // 所指为常量 int* const pSomeValue = someValue // 指针为常量 const int* const pSomeValue = someValue // 两者皆是常量
void foo(const dataType* arg) // 传入一个指向常量的指针 void foo(dataType const* arg) // 与上面相同 在*左次序颠倒没有区别
迭代器也是指针衍生出来的,所以
std::vector<int> vec; ... const std::vector<int>::iterator iter = vec.begin(); // 迭代器的作用就像一个 T* const (模板变量的常量指针) *iter = 12345; // ok! 指针所指不是常量 ++iter; // error! 指针本身是常量 std::vector<int>::const_iterator cIter = vec.begin(); // cIter的作用如同一个 const T* (模板常量的变量指针) *cIter = 12345; // error! 指针所指是常量 ++cIter; // ok! 指针本身不是常量
将const应用于函数声明
良定义的数据类型应尽量避免隐式类型转换,这时返回一个常量值就十分有用
class Rational {...}; const Rational operator+ (const Rational& lhs, const Rational rhs); const Rational operator* (const Rational& lhs, const Rational rhs); ...
这样定义, if(a * b = c) // 本意是想做一个if(a * b == c)的比较 这样的错误就不会出现,而会被编译器直接警告。
2. const成员函数
使用const来控制成员函数对对象的可读写性是很重要的,因为这样可以使class借口更容易被理解,并且还可以使操作const对象成为可能。这对高效编写代码很重要。
class SomeText { public: ... const char& operator[](std::size_t position) const { return text[position]; } char& operator[](std::size_t position) { return text[position]; } } SomeText text("Hello,world!"); std::cout << text[0]; // 调用non-const方法 可以读 text[0] = 'A'; // 调用non-const方法 可以写 const SomeText cText("Hello,world!"); std::cout << cText[0]; // 调用const方法 可以读 cText[0] = 'A'; // 调用const方法 不可写!
对于在const中也想改变的量,使用mutable可以声明在const成员函数内依旧可被更改的变量。
如果成员函数代码功能相同而只有常量变量的区别,可以const_cast,static_cast来避免代码重复。
class SomeText { public: ... const char& operator[](std::size_t position) const { ... ... ... return text[position]; } char& operator[](std::size_t position) { return const_cast<char&> // 移除返回值的const (static_cast<const SomeText&> // 为*this加上const (*this)[position]); // 调用const op[] }
? 变量与对象的初始化与代码规范
1. 代码规范:
类型 | 规范 | 示例 |
简单数据类型 | 首字母小写表示类型,之后按单词分割每单词首字母大写。 |
int iMaxNum = 10000; char cRank = 'A'; string sName = "LevisonChen"; double dSpeed = 1.357; int* pMaxNum = iMaxNum; |
复杂数据类型 | 首字母小写,首词表示数据类型,之后按单词分割每单词首字母大写 |
std::vector<int> vecEdges;
|
函数 | 按单词分割每单词首字母大写 |
void Foo(){ ... } int GetMaxinum(std::vector<int> vecArg){ ... } |
类与结构体 | 按单词分割每单词首字母大写,私有字段不使用首词表示数据类型 |
class SomeClass { ... } struct SomeStruct { ... } |
缩进 | tab-4spaces缩进 |
{
...
{
...
{
...
...
...
}
...
}
...
}
|
2. 不要混淆赋值(assignment)和初始化(initialization)
class Person { public: Person(const std::string& sName, const std::int& iAge, const std::list<PhoneNumber>& listPhones, const std::list<EmailAddress>& listEmails); private: std::string name; std::int age; std::list<PhoneNumber> phones; std::list<EmailAddress> emails; }; Person::Person(const std::string& sName, const std::int& iAge, const std::list<PhoneNumber>& listPhones, const std::list<EmailAddress>& listEmails) { name = sName; age = iAge; phones = listPhones; emails = listEmails; } // 这是赋值而非初始化!
Person::Person(const std::string& sName, const std::int& iAge, const std::list<PhoneNumber>& listPhones, const std::list<EmailAddress>& listEmails) :name(sName), age(iAge), phones(listPhones), emails(listEmails) // 这是初始化! {}
为了消除跨编译时的单元初始化次序问题,应以local static对象替换non-local static对象。
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- C++ 转换函数搭配友元函数 2020-06-10
- C++ 自动转换和强制类型转换(用户自定义类类型) 2020-06-10
- C++ rand函数 2020-06-10
- C++ 友元函数 2020-06-10
- C++ 运算符重载 2020-06-10
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash