c++算法习题知识点

9.20

对比for循环和while循环,两种形式的优缺点各是什么?

在循环次数已知的情况下,for循环的形式显然更为简洁

而循环次数无法预知时,用while循环实现更适合。用特定条件控制循环是否执行,循环体中执行的语句可能导致循环判定条件发生变化

9.20

类型int、long、long long和short的区别是什么?无符号类型和带符号类型的区别是什么?float和double的区别是什么?

出题思路

本体旨在考察c++语言中几种主要算术类型的区别以及符号的表示方式和意义,该读者需要重点理解几种算法类型在内存中的存储方式

解答

在c++语言中,int、long、long long和short都属于整型,区别是c++标准规定的尺寸的最小值(即该类型在内存中所占的比特数)不同。其中,short是短整型,占16位;int是整型,占16位;long和long long均为长整型,分别占32位和64位。c++标准允许不同的编译器赋予这些类型更大的尺寸,某一类型占的比特数不同,它所能表述的数据范围也不一样。

大多数整形都可以划分为无符号类型和带符号类型,在无符号类型中所有比特都用来存储数值,但是仅能表示大于等于0的值;带符号类型则可以表示正数、负数或0.

float和double分别是单精度浮点数和双精度浮点数。区别主要是在内存中所占的比特数不同,以及默认规定的有效位数不同

9.22

声明与定义的关系是:声明使得名字为程序所知,而定义负责创建与名字关联的实体!

引用:必须指向一个实际存在的对象而非字面值常量!且我们无法令引用重新绑定到另外一个对象,所有引用必须初始化!

引用与对象关系:为引用赋值实际上是吧值赋给了与引用绑定的对象

                      以引用作为初始值实际上是以引用绑定的对象作为初始值

注意:引用不是对象,它只是为已经存在的对象起了另外一个名字,是对象别名!

指针和引用的主要区别:

指针和引用同为复合类型,都与内存中实际存在的对象有联系。

指针”指向“内存中的某个对象,而引用”绑定到“内存中的某个对象,它们都是实现了对其他对象的间接访问,二者的区别主要有两方面:

第一:指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以指向几个不同的对象;引用不是一个对象,无法另引用重新绑定到另外一个对象。

第二:指针无须再定义时赋初值,和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值;引用则必须在定义时赋初值。

nullptr和null区别

nullptr是一个无类型的东西,而且是一个宏。0为null pointer constan的。

赋予null pointer,应该是使用0,而非NULL。

nullptr是有类型的(放了在stddef头文件中),类型是typdef decltype(nullptr)nullptr_t;

给定指针p,你能知道它是否指向了一个合法的对象吗?如果能,叙述判断的思路;如果不能说明原因。

在c++程序中,应该尽量初始化所有指针,并且尽可能等定义了对象之后再定义指向它的指针。如果实在不清楚指针应该指向何处,就把它初始化为nullptr或者0,这样程序就能检测并知道它有没有指向一个具体的对象了。其中,nullptr是c++11新标准刚刚引入的一个特殊的字面值,它可以转换成任意其他的指针类型。在此前提下,判断p是否指向合法的对象,只需吧p作为if语句的条件即可,如果p的值是nullptr,则条件为假;反之,条件为真。

如果不注意初始化所有指针而贸然判断指针的值,则有可能引发不可预知的结果,一种处理的办法是把if(p)置于try结构中,当程序块顺利执行时,表示p指向了合法的对象;当程序块出错跳转到catch语句时,表示p没有指向合法的对象!

const限定符用法:const对象一旦创建后其值就不能改变,所有const对象必须初始化!

顶层const和底层const区别:顶层const表示任意的对象是常量,而底层const与指针和引用等符合类型的基本类型部分有关。在执行拷贝操作时,顶层const和底层const区别明显。其中,顶层const不受影响,这是因为拷贝操作并不会改变被拷贝对象的值。底层const的限制则不容忽视,拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换,一般来说,非常量可以转换成常量,反之则不行!

auto说明符与复合类型、常量混合使用时的各种情形。首先,使用引用其实是使用引用的对象,所有当引用被用作初始值时,真正参与初始化的其实是引用对象的值,编译器以引用对象的类型作为auto的推断类型,其次,auto一般会忽略掉顶层const,同时保留底层const

9.23

decltype的参数既可以是普通变量,也可以是一个表达式,当参数是普通变量时,推断出的类型就是该变量的类型;当参数是表达式时,推断出的类型就是引用

auto与decltype的区别主要有三个方面:

第一:auto类型说明符用编译器计算变量的初始值来推断期类型,而decltype虽然也让编译器分析表达式并得到它的类型,但是不实际计算表达式的值。

第二:编译器推断出来的auto类型有时候和初始值的类型并不完全一样,编译器会适当地改变结果类型使其更符合初始化规则。列如,auto一般会忽略掉顶层const,而把底层const保留下来。与之相反,decltype会保留变量地顶层const。

第三,与auto不同,decltype的结果类型与表达式形式密切相关,如果变量名加上了一对括号,则得到的类型与不加括号时会有不同。如果decltype使用后的是一个不加括号的变量,则得到的结果就是该变量的类型;如果给变量加上了一层或者多层括号,则编译器将推断得到引用类型。

9.24

两种重要的标准库类型,它们分别是string和vector

string表示可变长字符串,它的初始化方式分为两种:直接初始化和拷贝初始化。如果要处理string中的单个字符,我们可以使用c++11新定义的范围for语句,也可以使用下标运算符执行随机访问

vector表示对象的集合,其中所有对象的类型相同。如果要向vector对象中添加元素,必须使用push_back()函数,不允许使用下标形式添加元素。

迭代器和数组:

迭代器提供与指针功能类似的间接访问操作,迭代器可以执行解引用、与整数相加、比较、两个整数相减等操作,但是不能直接把两个迭代器相加。

与vector一样,数组也表示同类型对象的集合,但是vector的长度不固定,而数组的容量是固定不变的。在c++11新标准下,我们可以使用与迭代器类似的begin和end函数确定数组的边界。

using声明是作为替代,从而使的程序更加简洁直观。

9.25

请说明string类的输入运算符和getline函数分别是如何处理空白字符的

标准库string的输入运算符自动忽略字符串开头的空白(包括空格符、换行符、制表符等),从第一个真正的字符开始读起,直到遇见下一处空白为止。

如果希望在最终的字符串中保留输入时的空白符,应该使用getline函数代替原来的>>运算符,getline从给定的输入流中读取数据,直到遇到换行符为止,此时换行符也被读取进来,但是并不会存储在最后的字符串中。

在C++语言中tolower()函数是把字符串都转化为小写字母

                  touppre()函数是把字符串都转化为大写字母

其中需要注意的是:这两个函数的声明在头文件<cctype>中,但是经过测试,如果不包含头文件<cctype>仅仅有<iostream>也是可以的

vector对象的下标运算符只能用于访问已经存在的元素,而不能用于添加元素。要想向vector对象中添加新元素,需要使用push_back函数

迭代器是一种访问容器元素的通用机制,与指针类型类似,迭代器也提供了对象间接访问。使用迭代器可以访问某个元素,迭代器也能从一个元素移动到另一个元素。如果只需要输出vector对象的内容而无需对其进行更改,使用的迭代器应该是cbegin和cend,而非begin和end。需要更该vector对象的内容,使用begin和end。

其中begin指向容器的首元素而end指向容器的最后一个元素的下一个位置。

迭代器的运算类型及含义

c++并没有定义两个迭代器的加法运算,实际上直接把两个迭代器加起来是没有意义的。

与之相反,c++定义了迭代器的减法运算,两个迭代器相减的结果是它们之间的距离,也就是说,将运算符右侧的迭代器向前移动了多少个元素后可以的到左侧的迭代器,参与运算的两个迭代器必须指向同一个容器中的元素或尾后元素。

另外c++还定义了迭代器与整数的加减法运算,用以控制迭代器在容器中左右移动。

empty()函数

是用来测试变量是否已经配置。若变量已存在、非空字符串或者非零,则返回 false 值;反之返回 true值。所以,当字符串的值为0时,也返回true,就是执行empty内部的语句。这就是陷阱。

数组是一种复合类型,其声明形如a[b],a是数组的名字,b是数组的维度(容量)。对数组维度的要求有两个,一是维度表示数组中元素的个数,因此必须大于0;二是维度属于数组类型的一部分,因此在编译时应该是已知的,必须是一个常量表达式。

数组与vector的相似之处是都能存放类型相同的对象。且这些对象本身没有名字,需要通过其所在位置访问。

数组与vector最大不同是,数组大小固定不变,不能随意向数组中增加额外的元素,虽然在某些情境下运行时性能较好,但是与vector相比损失了灵活性!

constexpr函数指的是在编译的时候就能得到其返回值的函数,也就是说编译器将constexpr函数直接转换成其返回值,因此,constexpr函数都是被隐式地定义为内联函数。使用constexpr关键字来修饰constexpr函数。

为什么两个指针相加没有意义

指针也是一个对象,与指针相关的属性有3个,分别是指针本事的值(value),指针所指的对象(content)以及指针本身在内存中的存储位置(address)。它们的含义分别是:

指针本身的值是一个内存地址值,表示指针所指对象在内存中的存储地址:指针所指的对象可以通过解引用指针访问;因为指针也是一个对象,所以指针也存储在内存的某个位置,它有自己的地址,这也是为什么有“指针的指针”的原因。

通过上述分析我们知道,指针的值是它所指对象的内存地址,如果我们把两个指针加在一起,就是试图把内存中两个对象的存储地址加在一起,这显然是没有任何意义的。与之相反,指针的减法是有意义的。如果两个指针指向同一个数组中不同元素,则它们相减的结果表征了它们所指的元素在数组中的距离。

C风格字符串操作函数定义在cstring头文件中。其中,strcpy函数负责把字符串的内容拷贝给另一个字符串,strcat函数则负责把字符串的内容拼接到另一个字符串之后。此外。strlen函数用于计算字符串的长度。

C++不允许用一个数组初始化另一个数组,也不允许使用vector对象直接初始化数组,但是允许使用数组来初始化vector对象,要实现这一目的,只需要指明拷贝区域的首元素地址和尾后地址!

C++允许使用数组直接初始化vector对象,但是不允许使用vector对象来初始化数组。如果想使用vector对象初始化数组,必须把vector对象的每个元素逐一赋值给数组

9.27

表达式

c++语言提供了一套丰富的运算符,它们分别是:

算术运算符

逻辑运算符和关系运算符

赋值运算符

递增和递减运算符

成员访问运算符

条件运算符

位运算符

sizeof运算符

逗号运算符

9.29

对于c++语言没有明确规定大多数二元运算符的求值顺序,给编译器优化留下余地。但实际上实在代码生成效率和程序潜在缺陷之间进行了权衡,有什么注意的嘛?

一:拿不准的时候最好用括号来强制让表达式的组合关系符合程序的逻辑要求。

二:一旦改变了某个运算对象的值,在表达式的其他地方就不要再使用这个运算对象了。

典型的算术运算规则

一、除法:整数相除结果还是整数,如果商含有小数部分,直接弃除。尤其当除法的两个运算对象的符号不同时,商为负,c++11新标准规定商一律向0取证。

二、取余:如果取余的两个运算对象的符号不同,则符号所在的位置不同运算,结果也不相同,

m%(-n)等于m%n,(-m)%n等于-(m%n)

溢出是何含义?

当计算结果超出类型所能表示的范围时,产生溢出。

溢出是一种常见的算术运算错误。因为在计算机中存储某种类型的内存空间有限,所以该类型的表示能力(范围)也是有限的,当计算的结果值超出这个范围时,就会产生未定义的数值,这种错误称为溢出。

逻辑与、逻辑或及相等性运算符运算对象求值的顺序

逻辑与、逻辑或执行短路求值,相等性运算符则正常计算两个运算对象的值。

对于逻辑与运算符来说,当且仅当两个运算对象都为真时结果为真;对于逻辑或运算符来说,只要两个运算对象中的一个为真结果就为真。

逻辑与运算符和逻辑或运算符都是先求左侧运算对象的值再求右侧运算对象的值,当且仅当左侧运算对象无法确定表达式的结果时才会计算右侧运算对象的值。这种策略就是短路求值。其策略是:对于逻辑与运算符来说,当且仅当左侧运算对象为真时才计算右侧运算对象;对于逻辑或运算符来说,当且仅当左侧运算对象为假时才计算右侧运算对象。

值得注意的是,逻辑与运算符和逻辑或运算符是c++中仅有的几个规定了求值顺序的运算符。相等性运算符的两个运算对象都需要求值,c++没有规定其求值顺序。

9.30

c++规定<, <=,>,>=优先级高于==、!=。

如果赋值运算符左右两个运算对象的i

类型不同,则右侧运算对象转换成左侧运算对象的类型;赋值运算符满足右结合律。

c++实现了两种递增运算符;即前置版本和后置版本,二者的工作机理有所区别,一般来说前置版本是更好的选择。简言之,如果在一条表达式中出现了递增运算符,则其计算规律是:++在前,现加1,后参与运算;++在后,先参与运算,后加+

& 按位与

|  按位或

&& 逻辑与

|| 逻辑或        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Y木子李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值