[C++ 面试基础知识总结]表达式和函数

[C++ 面试基础知识总结]表达式和语句

参考书籍:《C++ Primer》

目录

  • C 面试基础知识总结表达式和语句
    • 目录
    • 运算符优先级
    • 算数运算符
      • 运算对象转换
      • 商和余数
    • 逻辑运算符
    • 强制转换类型
    • 数组形参和返回
    • 不能返回局部函数的指针和引用
    • 重载函数
    • 预处理器变量
    • 函数指针

运算符优先级


算数运算符

运算对象转换

小整数类型(bool,char,short)进行运算时通常会提升成较大的整数类型int。

bool b = true;
bool b2 = -b;

最终得到b2值为true,原因在于bool值不能直接进行算数运算,需要转化成int,-b的结果是-1,不等于0,所以b2的值为真。

商和余数

C++11新标准则规定商一律向0取整,所以-(m)/n和m/(-n)都等于-(m/n),m%(-n)等于m%n,(-m)%n等价于-(m%n)。

-21/ -8 // 根据商向0取整的原则,结果为2
-21% -8 // 由于商为2,余数为(-21-(-8)*2)=-5

21/ -5 // 根据商向0取整的原则,结果为-4
21% -5 // 由于商为-4,余数为(21-(-5)*(-4))=1

逻辑运算符

&&和||都是短路求值,仅当左侧运算对象无法确定表示结果时才会计算右侧运算对象。

#include <iostream>

int _tmain(int argc, _TCHAR* argv[])
{
    auto i = 0;
    if (++i == 1 || ++i == 0)
    {
        cout << i << endl;
    }
    return 0;
}

输出结果为1,因为执行++i == 1后,已经可以判定整个表达式为真了,不用再去计算右侧运算对象了,++i == 0没有执行,所以只对i进行了一次递增操作。

强制转换类型

static_cast可以进行不包含底层const的类型转换,const_cast 只能改变运算对象的底层const。

const char *p;
static_cast<char*p>(p); // 错误,不能用static_cast转换掉const
const_cast<char*p>(p); // 正确,const_cast去掉了const属性
static_cast<string>(p); // 正确,字符串字面值转换成string类型
const_cast<string>(p); // 错误,const_cast只能改变常量属性

数组形参和返回

数组是无法拷贝的,所以我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。函数也不能返回数组,只能返回数组的指针或引用。

//以下两个函数是等价的
void print(const int*);
void print(const int[]);
//以下两个函数是等价的
void print(int (*a)[]);
void print(int a[][]);
// 返回一个有10个元素的整型数组的指针,函数有一个int类型的形参i
int (*func(int i))[10];
// C++11的尾置返回类型写法,与上述声明等价
auto func(int i) -> int(*)[10];
// C++11中可用decltype,需要注意decltype并不负责把数组转化成指针,需要在声明函数的时候加一个*
int a[10];
decltype(a) *func(int i);

不能返回局部函数的指针和引用

局部对象在函数完成后,它所占的的存储空间也随之被释放掉,因此,函数终止意味着局部变量的指针或引用将指向不再有效的内存区域。

const string &func(){
    string ret;
        if (!ret.empty())
        {
            return ret;
        }
        else
        {
            return "Empty";
        }
}

两个返回都是错误的,试图返回局部变量或局部临时值的引用。

重载函数

重载函数名字和返回类型相同,但形参列表不同。顶层const不影响传入函数的对象,而底层const会。

int func(int*);
int func(double*); //正确重载函数,用于double型指针
void func(int*); //错误,只有返回类型不同
int func(const int*); //底层const,正确重载函数,用于常量整型指针
int func(int* const); //顶层const,重复声明

如果在内层作用域中声明名字,将会隐藏外层作用域的同名实体。在不同的作用域无法重载函数名。

string read();
void func(const string&);
void func(double):
int _tmain(int argc, _TCHAR* argv[])
{
    bool read = false;
    //错误,声明变量也会隐藏同名函数
    string s = read();
    void func(int);
    //错误,内层作用域中的的func函数隐藏了外层的func函数,现在的func只能接收int型参数。
    func("value");
    //不会报错,但是调用的是void func(int)
    func(3.14);
    return 0;
}

确定某次调用该选用哪个重载函数时会进行函数匹配,如果有且仅有一个函数匹配情况优于其它所有函数,则匹配成功,否则会因调用二义性而失败。
匹配优先级:
1.精确匹配:类型相同,数组类型或函数类型转化成对应的指针,顶层const
2.转换const
3.类型提升
4.算数类型转换或指针转换
5.类类型转换

void f();
void f(int);
void f(int,int);
void f(double,double);

//匹配到 f(double,double)
f(3.14);
//二义性,关于前一个参数f(int,int)更优,而后一个f(double,double)更优。
f(2,3.14);

void ff(int);
void ff(short);
void ff(float);

//匹配到ff(int),小整数型会直接提升到int
ff('a');
//二义性,字面值3.14的类型是double,存在多种可能的算数型转换
ff(3.14);

预处理器变量

预处理定义的5个用于程序调试很有用的名字。

__FILE__  文件名
__func__  存放当前函数的名字
__LINE__  存放当前行号
__TIME__  存放文件编译时间
__DATE__  存放文件编译日期

函数指针

函数指针指向的是函数,它的类型由返回类型和形参共同决定。

bool func(int,int);
// p指向一个函数,该函数参数是两个int型整数,返回值是bool
bool (*p)(int,int);

//把函数名当作值使用会自动转化为指针,以下两个赋值等价
p = func;
p = &func;

//可以直接用指向函数的指针调用该函数,以下3个调用也等价
bool b1 = func(0,0);
bool b2 = p(0,0);
bool b3 = (*p)(0,0);
// f的形参为1个int型整数,返回值是一个指针,指向一个int*(int*,int)函数
int (*f(int))(int*,int);
// 等价写法
auto f(int) -> int*(int*,int)
时间: 2024-09-15 01:23:14

[C++ 面试基础知识总结]表达式和函数的相关文章

[C++ 面试基础知识总结]字符串,向量和数组

[C++ 面试基础知识总结]字符串,向量和数组 参考书籍:<C++ Primer> 目录 C 面试基础知识总结字符串向量和数组 目录 string string的读写 stringsize_type类型 string对象和字面值相加 vector容器 vector的初始化 使用vector的注意事项 迭代器 迭代器运算符 使用迭代器实现二分查找 数组 初始化和赋值 字符数组 数组与指针 C风格字符串 多维数组中的指针 string string的读写 #include <iostream

[C++ 面试基础知识总结] 泛型算法

[C++ 面试基础知识总结] 泛型算法 参考书籍:<C++ Primer> 目录 C 面试基础知识总结 泛型算法 目录 基础泛型算法 只读算法 写容器算法 重排容器元素算法 定制操作 向算法传递函数 lambda表达式 参数绑定 特殊迭代器 插入迭代器 iostream迭代器 反向迭代器 5类迭代器 链表的特定容器算法 基础泛型算法 泛型算法本身运行于迭代器之上,不会执行容器的操作,可以改变容器中保存元素的值,也可以在容器内移动元素,但永远不会直接添加或删除元素.插入迭代器是一种特殊的迭代器,

[C++ 面试基础知识总结] 顺序容器

[C++ 面试基础知识总结] 顺序容器 参考书籍:<C++ Primer> 目录 C 面试基础知识总结 顺序容器 目录 顺序容器与选择 迭代器 容器的初始化和赋值 顺序容器操作 添加元素 访问元素 删除元素 改变容器大小 迭代器失效 vector对象的增长 string 操作 改变string 搜索string 数值转换 容器适配器 栈stack 队列queue 顺序容器与选择 顺序容器类型: vector 可变大小数组 deque 双端队列 list 双向链表 forward_list 单向

[C++ 面试基础知识总结] 关联容器

[C++ 面试基础知识总结] 关联容器 参考书籍:<C++ Primer> 目录 C 面试基础知识总结 关联容器 目录 关联容器类型 关联容器概述 定义关联容器 关键字类型的要求 pair 关联容器操作 关联容器迭代器 添加元素 删除元素 访问元素 无序容器 关联容器类型 标准库共提供了8个关联容器 map 关联数组:保存关键字-值对 set 关键字即值,即只保存关键字的容器 multimap 关键字可重复出现的map multiset 关键字可重复出现的set unordered_map 用

[C++ 面试基础知识总结] 类

[C++ 面试基础知识总结] 类 参考书籍:<C++ Primer> 目录 C 面试基础知识总结 类 目录 类的基础 成员函数 构造函数 访问控制和封装 友元 名字查找与类的作用域 类的静态成员与普通成员 类的基础 成员函数 在成员函数中,可以直接访问数据成员,而在这个过程中实际上隐式地使用了一个名为this的隐式指针,该指针指向正是这个类对象. #include <iostream> using namespace std; struct People{ string name

Javascript基础知识盲点总结之函数_javascript技巧

函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块.本文重点给大家介绍js基础知识盲点总结之函数. 一.函数中的arguments对象 每个函数内部都有一个arguments,它能返回函数所接受的所有参数 注意:argumens接收的是实参 如下是利一个利用arguments特性编写的求和函数: function sumOnSteroids(){ var I, res = 0; var number_of_params = arguments.length; for(I = 0; I <

《C++ 黑客编程揭秘与防范(第2版)》——6.5 破解基础知识及调试API函数的应用

6.5 破解基础知识及调试API函数的应用 C++ 黑客编程揭秘与防范(第2版)在介绍完PE文件结构以后,接下来介绍调试API.调试API是系统留给用户进行程序调试的接口,其功能非常强大.在介绍调试API以前,先来回顾一下OD的使用.OD是用来调试应用程序的强大的工具.第5章中对其进行了简单的介绍,本章中将通过实例来回顾其强大功能.同样,为了后续的部分较容易理解,这里写一个简单程序,用OD来进行调试.除了介绍调试API以外,还会介绍一些简单的与破解相关的内容.当然,破解是一个技术的积累,也是要靠

javascript基础知识分享之类与函数化_基础知识

1.对象适合于收集和管理数据,容易形成树型结构. Javascript包括一个原型链特性,允许对象继承另一对象的属性.正确的使用它能减少对象的初始化时间和内存消耗. 2.函数它们是javascript的基础模块单元,用于代码复用.信息隐藏和组合调用.函数用于指定对象的行为.一般来说,编程就是将一组需求分解成一组函数和数据结构的技能. 3.模块我们可以使用函数和闭包来构造模块.模块是一个提供接口却隐藏实现状态和实现的函数或对象. 1.自定义类型--构造函数模式(伪类模式) 在基于类的系统中,对象是

Mysqli基础知识_Mysql

       相信原来在开始学习php的时候,很多人使用的数据库首选MySQL,连接数据库的扩展首选mysql扩展,但随着php版本的提高,mysql扩展正逐渐被mysqli和PDO所取代.正如使用mysql函数时给出的deprecated: The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead.学习mysqli扩展势在必行了. 相对于mysql扩展,mysql