C++知识点

std :: string和std :: wstring
标准库中的所有字符串功能都位于头文件中

#include<string>

标准库提供了两种basic_string <>:

namespace std
{
    typedef basic_string<char> string;
    typedef basic_string<wchar_t> wstring;
}

std :: string用于标准的ascii和utf-8字符串,std :: wstring用于宽字符/ unicode(utf-16)字符串
详见:https://www.learncpp.com/cpp-tutorial/17-1-stdstring-and-stdwstring/

提示:
您可能会认为使用较少内存的类型将比使用更多内存的类型更快。这并非总是如此。CPU经常被优化以处理特定大小(例如32位)的数据,并且可以更快地处理匹配该大小的类型。在这样的机器上,32位int可能比16位short或8位char更快

endl和’\n’的差别:
使用std :: endl可能效率有点低,因为它实际上有两个作业:1、它将光标移动到下一行,2、“刷新”输出(确保它立即显示在屏幕上)。当使用std :: cout将文本写入控制台时,std :: cout通常会刷新输出(如果没有,通常无关紧要),所以使用std :: endl flush刷新很重要。
因此,通常首选使用’\ n’字符。’\ n’字符将光标移动到下一行,但不执行冗余刷新,因此它的性能更好。’\ n’字符也更容易阅读,因为它更短并且可以嵌入到现有文本中

关于枚举:

enum string{    
    x1,    
    x2,    
    x3=10,    
    x4,    
    x5,    
} x;

枚举变量是全局变量的情况下, 枚举值的缺省值是0,不是枚举的第一个值。 其他情况,其值是不定的,而且不限定于所列出的枚举值

指针执行p++操作

unsigned char *p1;
unsigned long *p2;
p1=(unsigned char *)0x801000;
p2=(unsigned long *)0x810000;

请问p1+5= 什么?
p2+5= 什么?
解答:p1+5=p1+51=p1+5sizeof(unsigned char)=p1+51=0x801000+ox5=0x801005
p2+5=p2+5
1=p2+5sizeof(unsigned long)=p1+54=0x810000+20=0x810000+0x14=0x810014
最后要转换成16进制
p1指向字符型,一次移动一个字符型,1个字节;p1+5后移5个字节,16进制表示为5;
p2指向长整型,一次移动一个长整型,4个字节,p2+5后移20字节,16进制表示为14。
{ char每次移动1个字节;short移动2个字节 ;int , long ,float移动4个字节 ;double移动8个字节}

数组越界异常
处理a.html文件时,以下哪行伪代码可能导致内存越界或者抛出异常

int totalBlank = 0;
         int blankNum = 0;
         int taglen = page.taglst.size();
A       for(int i = 1; i < taglen-1; ++i)
        {
                 //check blank
B             while(page.taglst[i] == "<br>" && i < taglen)
               {
C                       ++totalBlank;
D                       ++i;
               }
E             if(totalBlank > 10)
F                      blankNum += totalBlank;
G             totalBlank = 0;
        }

解析:答案为B,因为while(page.taglst[i] == “
” && i < taglen)这个判断,先执行page.taglst[i] == "
"这个判断,如果这个判断返回值为true,再执行i < taglen这个判断。当i=taglen的时候,执行page.taglst[i] == "
"这个判断就会越界,所以B处,最先出现越界

sizeof运算符操作

void Func(char str_arg[100])
{
       printf("%d\n",sizeof(str_arg));
}
int main(void)
{
     char str[]="Hello";
     printf("%d\n",sizeof(str));
    printf("%d\n",strlen(str));
    char*p=str;
    printf("%d\n",sizeof(p));
    Func(str);
}

32位系统下下面程序的输出结果为多少?
答案:6 5 4 4
对字符串进行sizeof操作的时候,会把字符串的结束符"\0"计算进去的,进行strlen操作求字符串的长度的时候,不计算\0的,数组作为函数参数传递的时候,已经退化为指针了,Func函数的参数str_arg只是表示一个指针,那个100不起任何作用的

charstr[] = "glad to test something";                   //定义字符串

char*p = str;                                           //p指向字符串首地址,即字符'g'

p++;                                                    //p是char*类型,每次移动sizeof(char)字节,故此时p指向 'g'的下一个字符 'l'

int*p1 = reinterpret_cast<int*>(p);                     //指针p被重新解释为整型指针并被赋值给p1

p1++;                                                   //p1是int*类型, 每次移动sizeof(int)字节,故此时p1 指向 'l'后的第四个字符 't'

p = reinterpret_cast<char*>(p1);                        //指针p1被重新解释为字符型指针并被赋值给p

printf("result is %s\n", p);                            //从't'开始输出字符串,即得到 "to test something"

变量空间的堆栈分配
设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为?

C c;
void main()
{
    A*pa=new A();
    B b;
    static D d;
    delete pa;
}

答案:A B D C
解析:这道题主要考察的知识点是 :全局变量,静态局部变量,局部变量空间的堆分配和栈分配

其中全局变量静态局部变量是从静态存储区中划分的空间,
二者的区别在于作用域的不同,全局变量作用域大于静态局部变量(只用于声明它的函数中),
而之所以是先释放 D 在释放 C的原因是, 程序中首先调用的是 C的构造函数,然后调用的是 D 的构造函数,析构函数的调用与构造函数的调用顺序刚好相反。

局部变量A 是通过 new 从系统的空间中分配的,程序运行结束之后,系统是不会自动回收分配给它的空间的,需要程序员手动调用 delete 来释放。

局部变量 B 对象的空间来自于系统的空间,在该方法执行结束就会由系统自动通过调用析构方法将其空间释放。

之所以是 先 A 后 B 是因为,B 是在函数执行到 结尾 “}” 的时候才调用析构函数, 而语句 delete a ; 位于函数结尾 “}” 之前

逗号运算符
逗号运算符允许您在允许单个表达式的任何位置计算多个表达式。逗号运算符计算其最右边的操作数

int x = 0;
int y = 2;
int z = (++x, ++y); // increment x and y

z将被赋予评估++ y的结果,其等于3

按位运算符

左移	<<	x << y	x中的所有位左移y位
右转	>>	x >> y	x中的所有位右移y位
按位NOT	〜	〜X	x中的所有位都被翻转
按位AND	&	x&y	x中的每个位和y中的每个位
按位OR	|	x | ÿ	x中的每个位或y中的每个位
按位异或	^	x ^ y	x中的每个位异或y中的每个位(0^1=1,0^0=0,1^1=0

位操作是少数几种应该明确使用无符号整数数据类型的情况之一。这是因为C ++不保证如何存储有符号整数,也不保证某些按位运算符如何应用于有符号变量
规则:处理位运算符时,使用无符号整数

位标记和位掩码
std :: bitset简介

#include <bitset>
 
std::bitset<8> bits; // we need 8 bits

如果需要,可以使用一组初始值初始化bitset:

#include <bitset>
 
std::bitset<8> bits(option1 | option2) ; // start with option 1 and 2 turned on
std::bitset<8> morebits(0x3) ; // start with bit pattern 0000 0011

std :: bitset提供了4个关键功能:

  • test()允许我们查询一个位是0还是1
  • set()允许我们开启一下(如果该位已经打开,这将无效)
  • reset()允许我们关闭一点(如果该位已经关闭,这将无效)
  • flip()允许我们从0翻转到1,反之亦然

这些函数中的每一个都采用位位置参数来指示应该操作哪个位。最右边的位的位置是0,随着每个连续的位向左增加。给位索引提供描述性名称在这里很有用(通过将它们分配给const变量,或者使用枚举,我们将在下一章中介绍)

#include <bitset>
#include <iostream>
 
// Note that with std::bitset, our options correspond to bit indices, not bit patterns
const int option0 = 0;
const int option1 = 1;
const int option2 = 2;
const int option3 = 3;
const int option4 = 4;
const int option5 = 5;
const int option6 = 6;
const int option7 = 7;
 
int main()
{
    std::bitset<8> bits(0x2); // we need 8 bits, start with bit pattern 0000 0010
    bits.set(option4); // set bit 4 to 1 (now we have 0001 0010)
    bits.flip(option5); // flip bit 5 (now we have 0011 0010)
    bits.reset(option5); // set bit 5 back to 0 (now we have 0001 0010)
 
    std::cout << "Bit 4 has value: " << bits.test(option4) << '\n';
    std::cout << "Bit 5 has value: " << bits.test(option5) << '\n';
    std::cout << "All the bits: " << bits << '\n';
 
    return 0;
}

打印:

位4的值为:1
位5的值为:0
所有位:00010010

请注意,将bitset变量发送到std :: cout会打印bitsets中所有位的值
请记住,bitset的初始化值被视为二进制,而bitset函数使用位位置

位掩码
位标志的原理可以扩展为在单个操作中一次打开,关闭,切换或查询多个位。当我们将各个位捆绑在一起以便将它们作为一组进行修改时,这称为位掩码。

我们来看一下使用位掩码的示例程序。在以下程序中,我们要求用户输入一个数字。然后,我们使用位掩码仅保留低4位,我们打印的值为

#include <iostream>
 
int main()
{
    const unsigned int lowMask = 0xF; // bit mask to keep low 4 bits (hex for 0000 0000 0000 1111)
 
    std::cout << "Enter an integer: ";
    int num;
    std::cin >> num;
 
    num &= lowMask; // remove the high bits to leave only the low bits
 
    std::cout << "The 4 low bits have value: " << num << '\n';
 
    return 0;
}

输入一个整数:151
4个低位具有值:7

151是二进制的1001 0111,lowMask是8位二进制的0000 1111,1001 0111&0000 1111 = 0000 0111,即小数点后7位,虽然这个例子非常人为,但要注意的重要一点是我们在一次操作中修改了多个位!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值