笔试整理之C++基础试题

1、i++跟++i

(1)单独执行后,i的值都增加了1


(2)i++不可以做左值,++i可以

<1>左值:C/C++语言中可以放在赋值符号左边的变量,即具有对应的可以由用户访问的存储单元,并且能够由用户去改变其值的量。

<2>具体函数实现:

// 前缀形式:

int& int::operator++() //这里返回的是一个引用形式,就是说函数返回值也可以作为一个左值使用
{//函数本身无参,意味着是在自身空间内增加1的
  *this += 1;  // 增加
  return *this;  // 取回值
}

//后缀形式:
const int int::operator++(int) //函数返回值是一个非左值型的,与前缀形式的差别所在。
{//函数带参,说明有另外的空间开辟
  int oldValue = *this;  // 取回值
  ++(*this);  // 增加
  return oldValue;  // 返回被取回的值

}


2、C++ 的一个常见面试题是让你实现一个 String 类,限于时间,不可能要求具备 std::string 的功能,但至少要求能正确管理资源。

此题转载至:http://coolshell.cn/articles/10478.html

首先选择数据成员,最简单的 String 只有一个 char* 成员变量。

好处是容易实现,坏处是某些操作的复杂度较高(例如 size() 会是线性时间)。

为了面试时写代码不出错,本文设计的 String 只有一个 char* data_成员。

而且规定 invariant 如下:一个 valid 的 string 对象的 data_ 保证不为 NULL,data_ 以 '\0' 结尾,以方便配合 C 语言的 str*() 系列函数。
其次决定支持哪些操作,构造、析构、拷贝构造、赋值这几样是肯定要有的(以前合称 big three,现在叫 copy control)。

如果钻得深一点,C++11的移动构造和移动赋值也可以有。

为了突出重点,本文就不考虑 operator[] 之类的重载了。

这样代码基本上就定型了:

 
 
  1. #include <utility> 
  2. #include <string.h> 
  3.   
  4. class String 
  5.  public
  6.   String() 
  7.     : data_(new char[1]) 
  8.   { 
  9.     *data_ = '\0'
  10.   } 
  11.   
  12.   String(const char* str) 
  13.     : data_(new char[strlen(str) + 1]) 
  14.   { 
  15.     strcpy(data_, str); 
  16.   } 
  17.   
  18.   String(const String& rhs) 
  19.     : data_(new char[rhs.size() + 1]) 
  20.   { 
  21.     strcpy(data_, rhs.c_str()); 
  22.   } 
  23.   /* Delegate constructor in C++11 
  24.   String(const String& rhs) 
  25.     : String(rhs.data_) 
  26.   { 
  27.   } 
  28.   */ 
  29.   
  30.   ~String() 
  31.   { 
  32.     delete[] data_; 
  33.   } 
  34.   
  35.   /* Traditional: 
  36.   String& operator=(const String& rhs) 
  37.   { 
  38.     String tmp(rhs); 
  39.     swap(tmp); 
  40.     return *this; 
  41.   } 
  42.   */ 
  43.   String& operator=(String rhs) // yes, pass-by-value 
  44.   { 
  45.     swap(rhs); 
  46.     return *this
  47.   } 
  48.   
  49.   // C++ 11 
  50.   String(String&& rhs) 
  51.     : data_(rhs.data_) 
  52.   { 
  53.     rhs.data_ = nullptr; 
  54.   } 
  55.   
  56.   String& operator=(String&& rhs) 
  57.   { 
  58.     swap(rhs); 
  59.     return *this
  60.   } 
  61.   
  62.   // Accessors 
  63.   
  64.   size_t size() const 
  65.   { 
  66.     return strlen(data_); 
  67.   } 
  68.   
  69.   const char* c_str() const 
  70.   { 
  71.     return data_; 
  72.   } 
  73.   
  74.   void swap(String& rhs) 
  75.   { 
  76.     std::swap(data_, rhs.data_); 
  77.   } 
  78.   
  79.  private
  80.   char* data_; 
  81. }; 

注意代码的几个要点:

  1. 只在构造函数里调用 new char[],只在析构函数里调用 delete[]。
  2. 赋值操作符采用了《C++编程规范》推荐的现代写法。
  3. 每个函数都只有一两行代码,没有条件判断。
  4. 析构函数不必检查 data_ 是否为 NULL。
  5. 构造函数 String(const char* str) 没有检查 str 的合法性,这是一个永无止境的争论话题。这里在初始化列表里就用到了 str,因此在函数体内用 assert() 是无意义的。

这恐怕是最简洁的 String 实现了。

练习1:增加 operator==、operator<、operator[] 等操作符重载。

练习2:实现一个带 int size_; 成员的版本,以空间换时间。

练习3:受益于右值引用及移动语意,在 C++11 中对 String 实施直接插入排序的性能比C++98/03要高,试编程验证之。(g++的标准库也用到了此技术。)


3.描述在浏览器中敲入一个网址并按下回车后所发生的事情//比如 www.baidu.com


(1)DNS域名解析

首先要查找域名的IP地址,经过DNS查找后,将输入网址域名转换成IP地址。如果url里不包含端口号,则会使用该协议的默认端口号。DNS域名解析的过程是这样的:首先我们知道我们本地的机器上在配置网络时都会填写DNS,这样本机就会把这个url发给这个配置的DNS服务器,如果能够找到相应的url则返回其ip,否则该DNS将继续将该解析请求发送给上级DNS,整个DNS可以看做是一个树状结构,该请求将一直发送到根直到得到结果。

(2)在发送请求前,先要建立一个TCP连接(socket连接)。socket通过ip和端口建立的,现在有了目标ip和端口号。

(3)建立连接后发送请求。浏览器给web服务器发送一个HTTP请求。请求中也包含浏览器存储的该域名的cookies。cookies是与跟踪一个网站状态相匹配的键值。cookies会存储登录用户名,服务器分配的密码和一些用户设置等。Cookies会以文本文档形式存储在客户机里,每次请求时发送给服务器。

(3)服务的永久重定向响应
(4)浏览器跟踪重定向地址
(5)服务器“处理”请求:应答 web服务器收到请求,进行处理。 从它的文档空间中搜索子目录index.html。如果找到该文件,Web服务器把该文件内容传送给相应的Web浏览器;未找到,返回错误信息。为了告知浏览器,Web服务器首先传送一些HTTP头信息,然后传送具体内容(即HTTP体信息),HTTP头信息和HTTP体信息之间用一个空行分开
(6)服务器发回一个HTML响应

(7)释放 TCP 连接:若connection 模式为close,则服务器主动关闭TCP 连接,客户端被动关闭连接,释放TCP 连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求
(8)浏览器开始显示HTML
(9)浏览器发送获取嵌入在HTML中的对象


参考网址:http://www.mamicode.com/info-detail-1357508.html


4.strcpy和memcpy的区别 ()

strcpy和memcpy都是标准C库函数,它们有下面的特点。
strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符。

已知strcpy函数的原型是:char* strcpy(char* dest, const char* src);
memcpy提供了一般内存的复制。即memcpy对于需要复制的内容没有限制,因此用途更广。
void *memcpy( void *dest, const void *src, size_t count );

char * strcpy(char * dest, const char * src) // 实现src到dest的复制
{
  if ((src == NULL) || (dest == NULL)) //判断参数src和dest的有效性
  {
      return NULL;
  }
  char *strdest = dest;        //保存目标字符串的首地址

  while ((*strDest++ = *strSrc++)!='\0'); //把src字符串的内容复制到dest下

  return strdest;
}


void *memcpy(void *memTo, const void *memFrom, size_t size)
{
  if((memTo == NULL) || (memFrom == NULL)) //memTo和memFrom必须有效
         return NULL;

  char *tempFrom = (char *)memFrom;             //保存memFrom首地址
  char *tempTo = (char *)memTo;                  //保存memTo首地址      
  while((size-- )> 0)                //循环size次,复制memFrom的值到memTo中
         *tempTo++ = *tempFrom++ ;  
  return memTo;



strcpy和memcpy主要有以下3方面的区别。
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy


  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值