[C++ 面试基础知识总结]表达式和函数-阿里云开发者社区

开发者社区> 艾土咻> 正文

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

简介: [C++ 面试基础知识总结]表达式和语句 参考书籍:《C++ Primer》 目录 C 面试基础知识总结表达式和语句 目录 运算符优先级 算数运算符 运算对象转换 商和余数 逻辑运算符 强制转换类型 数组形参和返回 不能返回局部函数的指针和引用 重载函数 预处理器变量 函数指针 运算符优先级 算数运算符 运算对象转换
+关注继续查看

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

参考书籍:《C++ Primer》

目录

运算符优先级

这里写图片描述
这里写图片描述

算数运算符

运算对象转换

小整数类型(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的形参为1int型整数,返回值是一个指针,指向一个int*(int*,int)函数
int (*f(int))(int*,int);
// 等价写法
auto f(int) -> int*(int*,int

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
正则表达式基础语法
“正则表达式”描述在搜索文本正文时要匹配的一个或多个字符串。该表达式可用作一个将字符模式与要搜索的字符串相匹配的模板。 正则表达式包括普通字符(例如,a到 z之间的字母)和特殊字符(称为“元字符”)。 特殊字符 下表包含了单字符元字符的列表以及它们在正则表达式中的行为。 注意 若要匹配这些特殊字符之一,必须首先转义字符,即,在字符前面加反斜杠字
880 0
C#委托基础8——lambda表达式
  C#委托基础系列原于2011年2月份发表在我的新浪博客中,现在将其般至本博客。 class Program { double AddInt(int x, int y) { return x + y; } string AddString(string s1, string s2)
801 0
Java基础-14总结正则表达式,Pattern,Mactcher,Math,BigInteger,BigDeximal,System等
你需要的是什么,直接评论留言。 获取更多资源加微信公众号“Java帮帮” (是公众号,不是微信好友哦) 还有“Java帮帮”今日头条号,技术文章与新闻,每日更新,欢迎阅读 学习交流请加Java帮帮交流QQ群553841695 分享是一种美德,分享更快乐! 学正则表达式之前qq号问题: package cn.itcast_01;
2012 0
【Java8新特性】Lambda表达式基础语法,都在这儿了!!
前面积极响应读者的需求,写了两篇Java新特性的文章。有小伙伴留言说:感觉Lambda表达式很强大啊!一行代码就能够搞定那么多功能!我想学习下Lambda表达式的语法,可以吗?我的回答是:没问题!这不,Lambda表达式来了!
19 0
Android面试题库 - Fragment(一) - 基础
Fragment为什么成为第五大组件 Fragment为什么成为第五大组件 四大组件:Activity、Service、Broadcast Receiver、Content Provider Fragment具有生命周期,使用广泛 Fragment加载...
1342 0
Android面试题库 - Activity(一) - 基础
Activity生命周期 什么是Activity 是一个应用组件,用户可与其提供的屏幕进行交互,以执行拨打电话、拍摄照片、发送电子邮件或查看地图等操作。 Activity的4种状态 名称 解释 running Activity处于前台,与用户...
1162 0
Android面试题库 - Service(一) - 基础
Service应用场景、与Thread的区别 Service是什么 Service是一个一种在后台长时间执行操作而有没有用户界面的应用组件。 Service与Thread的区别 Thread 最小的运行单元,可以用来执行耗时操作 Service 运行在主线程,不能做耗时操作 ANR 时间20s Service的两种启动方式 两种启动方式说明 启动 当应用组件(如 Activity)通过调用 startService() 启动服务时,服务即处于“启动”状态。
1000 0
C# 扩展方法 白话总结
我们在变成的时候时常遇到这样的问题,new了一个系统内的对象之后,我们想要对该对象有一个方法可是却点不出来,说明该对象本身没有声明该方法,可是微软又不允许我们去该对象的代码,怎么办? 在C# 3.
781 0
+关注
30
文章
3
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载