1.TCP 状态变迁中,存在 TIME_WAIT 状态,请问以下不正确的描述是?()
- A、 TIME_WAIT 状态可以帮助 TCP 的全双工连接可靠释放
- B、 TIME_WAIT 状态是 TCP 是三次握手过程中的状态
- C、 TIME_WAIT 状态是为了保证重新生成的 socket 不受之前延迟报文的影响
- D、 TIME_WAIT 状态是为了让旧数据包消失在网络中
2.下列TCP连接建立过程描述正确的是:
- A、 服务端收到客户端的SYN包后等待2*ml时间后就会进入SYN_SENT状态
- B、 服务端收到客户端的ACK包后会进入SYN_RCVD状态
- C、 当客户端处于ESTABLISHED状态时,服务端可能仍然处于SYN_RCVD状态
- D、 服务端未收到客户端确认包,等待2*ml时间后会直接关闭连接
3.在Linux系统中,以下哪两个命令可以显示系统中运行的进程状态
- A、 ls和df
- B、 ps和top
- C、 ps和df
- D、 df和top
ps和top都是从/proc目录下读取进程的状态信息,内核把当前系统进程的各种有用信息都放在这个伪目录下。
top命令反应的是系统进程动态信息,默认10s更新一次
ps命令提供系统过去信息的一次性快照
也就是说ps命令能够查看刚刚系统的进程信息 命令:ps aux或者ps lax
4.每天开机在/misc目录下创建一个当天日期的文件夹( )
- A、 echo "mkdir /misc/`date %Y%m%d`" >> /etc/rc.d/rc.local
- B、 echo "mkdir /misc/date +%Y%m%d">>/etc/rc.d/rc.local
- C、 echo "mkdir /misc/`date +%Y%m%d`">> /etc/rc.d/rc.local
- D、 echo "mkdir /misc/`date +%Y%m%d`">>/etc/rc.d/rc.local
/etc/rc.d/rc.local:一个启动加载配置文件,这个配置文件会在用户登陆之前读取,这个文件中写入了什么命令,在每次系统启动时都会执行一次。也就是说,如果有任何需要在系统启动时运行的工作,则只需写入 /etc/rc.d/rc.local 配置文件即可。把一个程序加入开机启动,一般也可以通过修改rc.local来完成。
>和>>:他们俩其实唯一的区别就是>是重定向到一个文件,>>是追加内容到文件。两个命令都是如果文件不存在则创建文件。
1>>、2>>、1>、2>:1表示运行程序时程序正确运行输出结果的重定向、1表示运行程序时时程序错误运行信息(如异常信息)的重定向,然后>>与>的区别和上面一样。
注:echo "mkdir /misc/date + %Y%m%d" >> /etc/rc.d/rc.local不一定在实际操作中有用,因为rc.local会被Linux的不同版本修改,如ubuntu中在case语句块里脚本就退出了,追加到文件尾部的话不会被执行。
5.调用recv(int sockfd, void *buf, size_t len, int flags)的过程中,一共进行了几次内存复制操作?
- A、 1
- B、 2
- C、 3
- D、 4
内核从对端接受数据,放在socket的缓存中,然后复制到应用层的buffer,所以一共两个buffer
6.假设一棵完全二叉树含有456个结点,则度为0、1、2的结点个数分别为( )
- A、 227,1,228
- B、 228,1,227
- C、 228,0,228
- D、 不确定
完全二叉树的性质: n个节点的完全二叉树,当n为奇数,每一个分支节点都有左右儿子,也就没有度为1的点。 当n为偶数,编号最大的那个分支节点只有左儿子,其他分支节点左右儿子都有,也就是会有一个度为1的点。 另外,非空二叉树的叶子节点比度为2的节点数量多1,即n0 = n1 + 1 。所以选B
7.后缀式 ab+cd+/可用表达式( )来表示
- A、 a+b/c+d
- B、 (a+b)/c+d
- C、 a+b/(c+d)
- D、 (a+b)/(c+d)
后缀表达式不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行,不再考虑运算符的优先规则。 最后一个操作是'/',而且前面是一个+操作,后面没有操作,可知/操作最后进行,由此可得,另外两个操作数是a+b和c+d,因此表达式为D (a+b)/(c+d)
8.定义class时,用户自己必须定义构造函数?
- A、 正确
- B、 错误
编译器自动生成默认构造函数、析构函数。
9.派生类中虚函数原型的()
- A、 函数类型可以与基类中虚函数的原型不同
- B、 参数个数可以与基类中虚函数的原型不同
- C、 参数类型可以与基类中虚函数的原型不同
- D、 以上都不对
C++规定虚函数在派生类中重新定义时,其函数原型,包括函数类型、函数名、参数个数、参数类型的顺序,都必须与基类中的原型完全相同
10.c++中右值解决了什么问题?
C++11之前我们这么写:
string result = "Hello, ";
result += name;
result += ".";
C++11之后:
string result = string("Hello, ") + name + ".";
实现移动语义,减少程序开销
1.返回值优化:当函数需要返回一个本地对象(栈空间)的时候,如果自己创建一个临时对象用于返回,那么这个临时对象会消耗一个构造函数(Constructor)的调用、一个复制构造函数的调用(Copy Constructor)以及一个析构函数(Destructor)的调用的代价。经过返回值优化,就可以将成本降低到一个构造函数的代价。这样就省去了一次拷贝构造函数的调用和一次析构函数的调用。
2.完美转发:在函数模板编程中,常有一种场景是把模板参数转发给另一个调用函数,这时候如果只提供值传递版本会显得效率太低。如果原来的值是左值,经std::forward处理后该值还是左值;如果原来的值是右值,经std::forward处理后它还是右值。-->引用折叠std::move和std::forward
(一)两者比较
1. move和forward都是仅仅执行强制类型转换的函数。std::move无条件地将实参强制转换成右值。而std::forward则仅在某个特定条件满足时(传入func的实参是右值时)才执行强制转换。
2. std::move并不进行任何移动,std::forward也不进行任何转发。这两者在运行期都无所作为。它们不会生成任何可执行代码,连一个字节都不会生成。
(二)使用时机
1. 针对右值引用的最后一次使用实施std::move,针对万能引用的最后一次使用实施std::forward。
2. 在按值返回的函数中,如果返回的是一个绑定到右值引用或万能引用的对象时,可以实施std::move或std::forward。因为如果原始对象是一个右值,它的值就应当被移动到返回值上,而如果是左值,就必须通过复制构造出副本作为返回值。
什么样的表达式会返回一个右值?
- 首先,除非是在return一个局部变量的时候,否则变量名肯定不是右值,因为它可以在这个表达式之后被反复使用。
- 其次,表达式返回值是左值引用的,肯定也不是右值,因为这意味着别人可能也会拥有这个引用,想想为什么我们不能在函数里面返回局部变量的左值引用。
- 第三,表达式的返回值是一个值类型(譬如说MakeVector返回的vector<int>),那么当我们对这个表达式求值的时候,返回值所代表的对象可以被看成一个右值。这个变量在大部分时间是一个左值,但是它毕竟 跟函数的返回值在语法上不是同一个对象 。
- 第四,表达式的返回值是右值引用的,那肯定就是右值了。但是我们不要看到T&&就认为这一定是一个右值引用,因为如果T代表的是U&的话,那么它还是左值,因为U& &&其实相当于U&。这叫 引用折叠 。
- 其它的,大部分时候都是右值。
凡是有名字的东西,都不是右值 。
forward的一大作用就是把声明为右值引用的参数传递给别人并且以后再也不使用它
最后复习一下forward和move的区别:
- forward用来把是一个引用的参数传递出去, 这个参数在形式上声明为右值引用 。
- move在传递 左值引用类型的对象 的同时,用来“声称”一个左值引用指向的对象已经再也不需要使用了。
最重要区别的就是, 被你传递的那个引用,到底被声明成哪种引用 ——尽管使用他们的时候都是左值引用。