算术操作符
1.
21 % -5; // machine-dependent: result is 1 or -4
21 / -5; // machine-dependent: result -4 or -5
2.
溢出
关系操作符与逻辑操作符
3.
bool 类型可转换为任何算术类型——bool 值
false 用 0 表示,而 true 则为 1
位操作符
4.
位操作符操纵的整数的类型可以是有符号的也可以是无符号的。如果操作数
为负数,则位操作符如何处理其操作数的符号位依赖于机器
对于位操作符,由于系统不能确保如何处理其操作数的
符号位,所以强烈建议使用 unsigned 整型操作数。
5.
~位取反
^位异或
|位或
&位与
6.
7.
8.
( (cout << "hi") << " there" ) << endl;
在这个语句中, 操作数"hi"与第一个 << 符号结合, 其计算结果与第二个 <<
符号结合,第二个 << 符号操作后,其结果再与第三个 << 符号结合
9.
cout << 10 < 42; // error: 等同于(cout << 10) < 42;
<的优先级比关系操作符、赋值操作符和条件操作符优先级高
要加括号:cout << (10<42);
赋值操作符
10.
“s2 = "OK";”的赋值结果是s2,即“OK”
所以s1 = s2 = "OK;"
是把OK赋给s2,将返回的s2赋给s1
11.
复制操作具有低优先级,优先级小于!=判断符,要加上括号
12.
13.
a = a(0) + a+1(1)
14.
++i 比 i++ 效率高,前置操作符只需加1后返回结果,而后置操作符需要先保存操作数原来的值,以便返回未加1前的值作为结果。
15.
*p++:输出p指向的数值,然后p自增。*对p的原值(为加1前的副本)进行解引用。
加上括号,结果一样:
*++p(奇怪的用法)
同理,加括号也一样
16.
你认为为什么 C++不叫做++C?
C++保留了C语言的原有内容,在此基础上增加其他特性,可以向下兼容C。
++C表示无法再使用C语言了。
17.
*(sp.same_isbn(item2)); // equivalent to *sp.same_isbn(item2);
18.
编写程序定义一个 vector 对象,其每个元素都是指向string 类型的指针,读取该 vector 对象,输出每个string 的内容及其相应的长度。
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 int main() 6 { 7 vector <string*> v; 8 string str; 9 while (cin >> str) 10 { 11 if (str =="exit")break; 12 string* sp = new string; 13 *sp = str; 14 v.push_back(sp); 15 } 16 vector<string*>::iterator it = v.begin(); 17 for (; it != v.end(); it++) 18 { 19 cout << **it << " size:" << (*it)->size() <<endl; 20 } 21 return 0; 22 }
19.
不合法:
20.
找最大值骚操作
21.
报错:
22.sizeof
23.求数组大小
24.
25.
优先级:
运算符从左到右结合。
26.=和*的优先级
*a++;//指针++再解引用
(*a)++;//解引用再++
返回函数返回值与1比较的结果。
先赋值,再比较。
27.
28.
如果先计算右边,是a[0]和a[0]比较
如果先计算左边,是a[0]和a[1]比较
29.
问:除了逻辑与和逻辑或外,C++ 没有明确定义二元操作符的求解次序,编译器可自由地提供最佳的实现方式。只能在“实现效率”和程序语言使用中“潜在的缺陷”之间寻求平衡。你认为这可以接受吗?说出你的理由。
答:大多数时候操作数求解的顺序对结果没有影响,“潜在的缺陷”只在极少数时候出现,且程序员可以弥补,而“实现效率”一直有效。
30.
ival++ && ival
判断ival的值是否等于ival的值,如果ival为false则无需往下判断。
31.
pa没有初始化,pb初始化为0。
()初始化只能放在类型名后面,不能放在变量名后面。
报错:
32.
C++ 没有明确定义如何释放指向不是用 new 分配的内存地址的指针。
如果指针的值是0,delete是合法的。
33.
delete后,指针变为垂悬指针,悬垂指针往往导致程序错误,而且很难检测出来。
所以在delete之后要马上将指针赋值为0。
34.
35.
如果是类类型的const动态对象
如果该类提供了默认的构造函数,则此对象可隐式初始化
如果没有默认构造函数,则需要显式初始化
new 表达式没有显式初始化 pcs 所指向的对象,而是隐式地将 pcs 所指向
的对象初始化为空的 string 对象。
36.
对同一个内存空间进行两次delete,可能会破坏自由存储区。
37.
删除const对象
尽管程序员不能改变 const 对象的值,但可撤销对象本身。如同其他动态
对象一样, const 动态对象也是使用删除指针来释放的
38.
push_back
back
pop_back
动态:
39.
试着操作pvec2[10],发现没有输出
将10改为9后有输出
结论:vector<string>* pvec2 = new vector<string>[10];的作用是申请了10个vector<string>,初始大小是0,大小不限,而new vector <string>(10)是申请了一个vector,这个vector大小为10。
40.
类型转换
如果两个类型之间可以相互转换,则称这两个类型相关。
将double赋给int,会被截断。
C++ 并不是把两个不同类型的值直
接加在一起,而是提供了一组转换规则,以便在执行算术操作之前,将两个操作
数转换为同一种数据类型。这些转换规则由编译器自动执行,无需程序员介入
——有时甚至不需要程序员了解。因此,它们也被称为隐式类型转换。
41.
42.
算数转换
原则:小的转为大的
最简单的转换为整型提升:对于所有比 int 小的整型,包括 char、signed
char、unsigned char、short 和 unsigned short,如果该类型的所有可能的值
都能包容在 int 内,它们就会被提升为 int 型,否则,它们将被提升为
unsigned int。如果将 bool 值提升为 int ,则 false 转换为 0,而 true 则
转换为 1。
有符号数和无符号数的转换:
包含 short 和 int 类型的表达式, short 类型的值转换为 int 。如果
int 型足够表示所有 unsigned short 型的值,则将 unsigned short 转换为
int,否则,将两个操作数均转换为 unsigned int 。例如,如果 short 用半字
表示而 int 用一个字表示,则所有 unsigned 值都能包容在 int 内,在这种机
器上, unsigned short 转换为 int。
43.
指针转换:
指向任意数据类型的指针都可转换为void*类型,整型数值常量0可转换为任意指针类型。
44.
转化为bool:
指针算数值为0,bool值为0,其他为true
bool转换为算术型:
true为1,false为0
45.
枚举型转换:
C++ 自动将枚举类型的对象或枚举成员( enumerator )转
换为整型,其转换结果可用于任何要求使用整数值的地方。
将 enum 对象或枚举成员提升为什么类型由机器定义,并且依赖于枚举成员
的最大值。无论其最大值是什么, enum 对象或枚举成员至少提升为 int 型。
如果 int 型无法表示枚举成员的最大值,则提升到能表示所有枚举成员值的、
大于 int 型的最小类型( unsigned int、long 或 unsigned long)。
46.
cosnt对象
当使用非 const 对象初始化 const 对象的引用时,系统将非 const 对象
转换为 const 对象。此外,还可以将非 const 对象的地址(或非 const 指针)
转换为指向相关 const 类型的指针
什么意思?
const int ci = 0;
const int *p = &ci; // ok: convert address of non-const to address of a const
47.
由标准库类型定义的转换
如while(cin >> s)
将istream转换为bool
如果最后一次读cin的尝试是成功的,转换为bool后获得true值,如果到达文件位,得false值
48.
显式转换
什么时候需要强制类型转换?
可以先将b转换为int,再进行运算:
49.
命名的强制类型转换:
命名的强制类型转换符号的一般形式如下:
cast-name<type>(expression);
其中 cast-name 为 static_cast、dynamic_cast、const_cast 和
reinterpret_cast 之一,type 为转换的目标类型,而 expression 则是被强制
转换的值。强制转换的类型指定了在 expression 上执行某种特定类型的转换
const_cast:去掉const属性
用const_cast进行其他类型转换,都会出现错误
50.
static_cast:编译器隐式执行的任何类型转换都可以由 static_cast 显式完成
用于将大的转换为小的:
对于从一个较大的算术类型到一个较小类型的赋值,编译器通常会产
生警告。当我们显式地提供强制类型转换时,警告信息就会被关闭
用于将存放在void*类型变量的指针值还原:
reinterpret_cast:用于处理无关类型之间的转换,
int *ip;
char *pc = reinterpret_cast<char*>(ip);
程序员必须永远记得 pc 所指向的真实对象其实是 int 型,而并非字符数
组。任何假设 pc 是普通字符指针的应用,都有可能带来有趣的运行时错误。例
如,下面语句用 pc 来初始化一个 string 对象:
string str(pc);
它可能会引起运行时的怪异行为。
用 pc 初始化 str 这个例子很好地说明了显式强制转换是多么的危险。问
题源于类型已经改变时编译器没有提供任何警告或错误提示。当我们用 int 型
地址初始化 pc 时,由于显式地声明了这样的转换是正确的,因此编译器不提供
任何错误或警告信息。后面对 pc 的使用都假设它存放的是 char* 型对象的地
址,编译器确实无法知道 pc 实际上是指向 int 型对象的指针。因此用 pc 初
始化 str 是完全正确的——虽然实际上是无意义的或是错误的。查找这类问题
的原因相当困难,特别是如果 ip 到 pc 的强制转换和使用 pc 初始化 string
对象这两个应用发生在不同文件中的时候。
51.
char *pc = (char*) ip;
或char *pc = char*(ip);
效果与reinterpret_cast相同
难以跟踪错误
52.
指出可能发生的(如果有的话)隐式类型转换:
(a)cval = 'a' + 3; (b) fval = ui – ival * 1.0;
(c)dval = ui * fval; (d) cval = ival + fval + dval;
【解答】
(a)'a'首先提升为int 类型,再将'a' + 3 的结果值转换为char 型,赋给cval。
(b)ival 转换为double 型与1.0 相乘,ui 转换为double 型再减去ival * 1.0
的结果值,减操作的结果转换为float 型,赋给fval。
(c)ui 转换为float 型与fval 相乘,结果转换为double 型,赋给dval。
(d)ival 转换为float 型与fval 相加,结果转换为double 型,再与dval 相加,
结果转换为char 型,赋给cval。
53.
integral promotions(整型提升)
整型提升是标准类型转换规则的子集, 它将较小的整型转换为最接近的较
大数据类型。 整型(如 short、 char 等) 被提升为 int 型或 unsigned int
型