第二章
1. 引用与指针
引用见上一篇文章;
// 执行完后,a和b的值都变成c
// 相当于b是a的小名
int a = 5;
int &b = a;
int c = 3;
b = c;
指针例子如下:
int x = 42;
int *ip = &x; // ip指向x的地址。
2. const
2.1 const与define的区别
摘自 helmsgao:http://blog.csdn.net/love_gaohz/article/details/7567856
(1) const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。
(2) 有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。、
(3) 提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
2.2 顶层const
顶层const(top-lever const)表示指针本身是一个常量;底层const(low-lever const)表示指针所指对象是一个常量。例子:
int i = 0
int *const p1 = &i; // 不能改变p1的值,这是一个顶层const
const int ci = 42; // 不能改变ci的值,这是一个顶层const
const int *p2 = &ci; // 允许改变p2的值,这是一个底层const
2.3 constexpr
允许将变量声明为constexpr类型,以便由编译器来验证变量的值是否是一个常量表达式。
3. 类型别名
方法一: typedefine
方法二:类型别名
// 方法一
typedef double wages;
wages w;
// 方法二
using SI = Sales_item;
作用:避免引用类的版本差异带来的程序大规模变化(来自python2、python3的经验)。
4. auto
auto的用法: qq_32541007(http://blog.csdn.net/qq_32541007/article/details/52424721)
(1)自动帮助推导类型
(2)类型冗长
(3)使用模板技术时,如果某个变量的类型依赖于模板参数,不使用auto将很难确定变量的类型(使用auto后,将由编译器自动进行确定)。
(4)返回值占位
// 2. 类型冗长
map<int, map<int,int> > map_;
map<int, map<int,int>>::const_iterator itr1 = map_.begin();
const auto itr2 = map_.begin();
auto ptr = []()
{
std::cout << "hello world" << std::endl;
};
// 3. 使用模板技术时,如果某个变量的类型依赖于模板参数,
// 不使用auto将很难确定变量的类型(使用auto后,将由编译器自动进行确定)。
template <class T, class U>
void Multiply(T t, U u)
{
auto v = t * u;
}
5. 绑定(bind)
令某个名字与给定实体关联在一起,使用改名字也就是使用该实体。例如,引用就是将某个名字与某个实体绑定在一起。
第三章
1. string
① string与string之间可以通过“+”连起来,但不能这样:string s = "hello"+"world"; 得这样: string s = "hello"+ str1 +"world"; 即中间得有一个str变量。
② for( auto c : str ) 取str中的每个字符。例子:
string s = "hello";
for(auto &c : s) // 注意c是引用
c = toupper(c);
cout << s << endl;
2. vector
也被称为“容器(container)”
关于使用vector还是数组,知乎上最高票的回答:https://www.zhihu.com/question/21760520
vector的大小是动态的,而且支持泛型,但执行效率数组>向量(https://www.cnblogs.com/love-yh/p/7410666.html)。
PS:只能对确知已存在元素执行下标操作!例子:
// 总之,就是可以把向量当做一种可扩容的数组来用。
vector<int> invec;
cout<<ivect[0]; // 错误,ivec不包含任何对象
vector<int> invec2(10);
cout<<ivect2[10]; // 错误,ivec2元素合法索引是0到9
3. 迭代器
之后会细讲,这里有一个用迭代器做二分搜索的例子:
auto beg = text.begin() ;
auto end = text.end() ;
auto mid = text.begin() + (end - beg)/2 ;
while ( mid != end && *mid != sought ){
if( sought < *mid)
end = mid ;
else
beg = mid + 1 ;
mid = beg + (end - beg)/2 ;
}
第四章
1.
位操作的操作数都会自动转化成int型(32位)。
【&】位与,【&&】逻辑与;
【|】位或,【||】逻辑或;
【^】位求反,【!】逻辑非。
【<<】左移位,【>>】右移位。
【sizeof】返回一个类型或一条表达式所占的字节数。
2.运算符优先级表
第六章
1. 函数技巧
① 使用引用(避免拷贝+传递多个参数)
因为拷贝大型类或容器对象比较低效,甚至有的类本身不支持拷贝操作,函数智能通过引用形参访问该类的对象。
例子:
// 比较两个string对象的长度
bool isShorter(const string &s1, const string &s2 )
{
return s1.size() < s2.size();
}
② 尽量使用常量引用
参考资料:stpease http://blog.csdn.net/stpeace/article/details/40871801
当函数无须修改引用形参的值时,最好使用常量引用。常量引用可接受参数范围比单纯的引用大。
2. main函数的命令行处理选项
int main(int argc, char *argv[]) {......}
第一个参数argc表示argv[]中字符串的数量,即在命令行中输入了几个参数。第二个参数argv[0]表示命令行的第一个输入的字符串(就是可执行文件名即程序名),argv[1]表示输入的第一个参数,argv[2]表示输入的第二个参数……
3. 返回值
不要反回局部对象的引用或指针,因为函数结束后,局部对象被释放,指针将指向不存在的对象。
4. 静态成员
静态成员能用于某些场景而普通成员不能。
静态成员独立于任何对象。静态成员可以作为默认实参,而非静态成员不行,因为它的值本身属于对象的一部分。
PS:印象里可以使用类的静态成员作为全局变量。
网友评论