C++刷题知识点总结1
1.表达式1/4+2.75的值是3。请问这个说法是正确的吗?
没有说明类型,假如是整型,则答案为2.若是浮点型,答案为3
2.strlen()计算字符数组的字符数,以"\0"为结束判断,不计算为’\0’的数组元素。
而sizeof计算数据(包括数组、变量、类型、结构体等)所占内存空间,用字节数表示。
3.不可重载运算符包括
. (成员访问运算符)
.* (成员指针访问运算符)
:: (域运算符)
?: (条件运算符)
sizeof (长度运算符)
4.中间件
中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。执行中间件的一个关键途径是信息传递。通过中间件,应用程序可以工作于多平台或OS环境。
(简单来说,中间件并不能提高内核的效率,一般只是负责网络信息的分发处理)
5.char a[5]
&a+1表示指向大小为5的下一个数组的指针
6.设语句定义char a[ 80 ]= " 0123\0789 "; ,则sizeof(a)和strlen(a)的值分别为
\078是一个八进制数,\0不可能是空字符,后接三位数表示一个八进制,但是本题\0接后三位的第三位是8,所以本题的全部字符分别为:
空格 0、1、2、3、\07、8、9 空格
80 和 9
7.能够把指定长度的字节序列插入到输出流中的函数是(B)
A.put B.write C.cout D.print
8.类模板的使用实际上是先将类模板实例化为模板类,再实例化成一个具体的类。
9.inline关键字
1.使用 inline 关键字的函数只是用户希望它成为内联函数
2.头文件中不仅要包含 inline 函数的声明,而且必须包含定义,且在定义时必须加上 inline 。【关键字 inline 必须与函数定义体放在一起才能使函数成为内联,仅将 inline 放在函数声明前面不起任何作用】
3.类内的成员函数,默认都是 inline 的。【定义在类声明之中的成员函数将自动地成为内联函数】
有哪几种情况只能用intialization list 而不能用assignment?
A.当类中含有const成员变量
B.基类无默认构造函数时,有参的构造函数都需要初始化。
C.当类中含有reference成员变量
D.当类中含有static成员变量
(1)有 const 修饰的成员函数(指 const 放在函数参数表的后面,而不是在函数前面或者参数表内),只能读取数据成员,不能改变数据成员;没有 const 修饰的成员函数,对数据成员则是可读可写的。
(2)常量(即 const)对象可以调用 const 成员函数,而不能调用非const修饰的函数。
12.类的实例化是在内存中分配一块地址,每个实例在内存中都有独一无二的二地址。同样,空类也会实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化后就有独一无二的地址了。所以,空类的sizeof为1,而不是0. 多重继承的空类的大小也是1.
第二种情况是编译器不同
13.原因在于unsigned char 这个数据类型,它占了 8位,表示范围是 0255(0000000011111111,八位)
14.数组指针
a+1跨越一个成员
&a+1跨越整个
#include "stdafx.h"
#include<iostream>
using namespace std;
struct S
{
int n;
char c[10];
} *p;
int main()
{
int b;
char c[1];
struct S a[3] = { { 3,"abc" },{ 5,"def" },{ 7,"ghi" } };
cout << a<<endl;
cout << a + 1<<endl;
cout << &a+1 << endl;
cout << sizeof(a)<<endl;
cout << sizeof(c) << endl;
cin >> b;
}
15.构造函数可以根据参数的不同实现函数重载,而因为析构函数没有参数,对于一个类来说也是唯一的,所以是不能重载的;
C++的派生类如果要覆盖一个继承到的成员函数,在基类中需要将该函数声明为virtual
构造函数不能声明为虚函数 析构函数中不能抛出异常
为什么析构函数不能抛出异常
为什么析构函数不能抛出异常
在Windows 32位操作系统中,假设字节对齐为4,对于一个空的类A,sizeof(A)的值为()?是1
在x86系统下,sizeof如下结构体的值是多少?
struct{
char a[10];
int b;
short c[3];
}
24
这个和当前工程配置编译器的优化等级有关,在VS05中Debug默认配置下,局部变量的间隔为12字节,栈占用的空间比较大,而且汇编代码也比较罗嗦,Release下的优化度就很大了,汇编可能都看不懂。
在 Visual Studio 开发环境中设置此编译器选项
打开此项目的“属性”对话框->C/C++ ->代码生成
修改下列属性之一或两者都修改:“基本运行时检查”或“较小类型检查”。
而且变量定义的顺序似乎与栈地址顺序无关。
char c[5] = { {‘a’},{‘b’} };
int b = 1024;
和
int b = 1024;
char c[5] = { {‘a’},{‘b’} };
的结果一样,都是b在高地址。可能因编译器不同而不同。
begin()返回指向第一个元素的迭代器,
end()返回最后一个元素的下一个元素的迭代器。
是这种类型:vector::iterator
vector::iterator itr;
使用的时候用(*itr)访问元素。
vector::erase方法,返回值是更新后的容器的被删除元素的后一个元素的迭代器。
左值和右值
一、引子
我们所谓的左值、右值,正确的说法应该是左值表达式、右值表达式。
因为C++的表达式不是左值就是右值。
在C中,左值指的是既能够出现在等号左边也能出现在等号右边的表达式,右值指的则是只能出现在等号右边的表达式。
而在C++中,二者的区别就不是这么简单了。
二、关键点
【官方定义】
一个左值表达式的求值结果是一个对象或者一个函数,而某些右值表达式的求值结果也是对象;
以常量对象为代表的某些左值并不能作为赋值语句的左侧运算对象。
归纳:当一个对象被用作右值的时候,用的是对象的值(内容);而被用作左值的时候,用的是对象的身份(在内存中的位置)。
【解读定义】
解读第一句:既然左值和右值都可以是对象,那怎么区分一个对象是左值还是右值呢?
左值:能用“取地址&”运算符获得对象的内存地址
右值:不能用“取地址&”运算符获得对象的内存地址
特例:因为可以用&取得字符串字面值常量的地址,所以它是一个左值;而其他的字面值常量则不可用&取地址,所以它们是右值
我们知道对象是一块空间,那么有哪些对象以及为什么不能用&取地址呢?
对于临时对象,它可以存储于寄存器中,所以没办法用“取地址&”运算符;
对于(非字符串)常量,它可能被编码到机器指令的“立即数”中,所以没办法用“取地址&”运算符。
解读第二句:字符串字面值常量确实不能放在等号左边啊,没错啊!
解读归纳:所以啊,左值看地址,右值看内容。
【补充】
#include <iostream>
using namespace std;
int& func(int &a)
{
return a; // 不能返回局部对象的引用
}
int main()
{
int a = 10;
func(a) = 100; // 返回非常量引用的函数可以当作左值使用
cout << a << endl; // 输出100
return 0;
}
三、为什么要区分左值右值
不同的运算符对运算对象的要求各不相同,有的需要左值运算对象、有的需要右值运算对象;返回值也有差异,有的得到左值结果、有的得到右值结果。
举例:使用关键字decltype的时候,其表达式的求值结果若是左值,decltype作用于该表达式(不能是变量)得到一个引用类型。例如,p的类型是int *,因为解引用运算符生成左值,所以decltype(*p)的结果是int &。而另一方面,因为取地址运算符生成右值,所以decltype(&p)的结果是int **,即结果是一个指向整型指针的指针。
又是辛勤劳作的一天。