c++语法拾遗,一些细节与特性
写了2年多的C+STL的acmer,在学习《C++ primer》时总结的一些少见的语法特性与细节。总体还是和题目说的一样这是一篇 c++ 拾遗。
1 变量和基本类型
1.1 基本类型
1.1.1 字面常量
0123 表示的不是带有前导0的数字123,而是代表8进制数字123。
1.2 常量
1.2.1 constexpr
constexpr变量能自动判别赋值的表达式是否是常量表达式,若不是则会报错。
constexpr int mf=20; //20是常量表达式
constexpr int limit=mf+1; //mf+1是常量表达式
constexpr int sz=size(); //当size是一个constexpr 函数的时候是是常量表达式
int a=20;
constexpr int b=a+1; //报错
1.2 处理类型
1.2.1 decltype
decltype能和auto类似的自动判别类型。
decltype(f()) a=b; //这里的a的类型是f()返回值的类型
编译器并不实际调用函数f,只是将返回值作为a的类型。
实际上decltype(exp) exp是一个表达式所以可以这么写
int a = 0;
decltype(a) b = 1; //b 被推导成了 int
decltype(10.8) x = 5.5; //x 被推导成了 double
decltype(x + 100) y; //y 被推导成了 double
- 如果 exp 是一个不被括号( )包围的表达式,或者是一个类成员访问表达式,或者是一个单独的变量,那么 decltype(exp) 的类型就和 exp 一致。
- 如果 exp 是函数调用,那么 decltype(exp) 的类型就和函数返回值的类型一致。
- 如果 exp 是一个左值,或者被括号( )包围,那么 decltype(exp) 的类型就是 exp 的引用。
2 表达式
2.1 基础
2.1.1 左值
简单的一句话说,左值就是内存。
2.1.2 右值
简单的一句话说,右值就是数据。
2.1.3 求值顺序
c++ 中没有定义表达式的求值顺序,如:
int cnt=0;
int f(){
return ++cnt;
}
int main(){
int a=f()-f(); //a的结果可能会因为编译器不同而不同
//因为两个f函数的调用顺序没有定义
return 0;
}
int a=1;
int b=a+a++; //同样,i的自增和i的调用顺序没定义
int c=a++ + ++a; //同样无定义
int *d= new int[2];
*d=f(*d++); //无定义
另外java是有定义表达式的求值顺序的,从左到右。c++不定义是为了编译器启用更多优化。
3 函数
3.1 可变参数的函数
3.1.1 initializer_list 形参
int sum(initializer_list<int> li){
int s=0;
for(auto i : li)
s+=i;
return s;
}
// 调用方法
sum({1,2,3,4,5});
sum({1,1,1,1});
initializer_lsit 对象中的元素永远是常量类型。
可使用begin、end、size方法进行操作。
3.1.2 省略符形参
void f(...);
void f(cnt,...);
不建议使用,仅为方便c++访问某些c代码设置。
3.2 函数返回
3.2.1 值如何被返回的
值返回的时候回调用拷贝构造函数,创建一个临时对象。
3.2.2 列表返回值
C++11 新标准规定,函数可以返回花括号包围的值的列表。
vector<int> f(){
return {1,2,3,4};
}
实际上就是花括号赋值,因为值返回的时候回调用拷贝构造函数,如果拷贝构造函数支持花括号,那就可以作为返回值。
3.2.3 返回数组指针
int (*f)()[size]; //表示函数f返回长度为size的数组指针
//特别的是这里数组表示是后置的
3.2.4 尾值返回类型
在C++11标准中添加了一种尾置返回类型的定义。
auto f()->int; //同等于 int f();
auto f()->int *[size]; //同等于 int (*f)()[size];
3.3 重载
3.3.1重载与const 形参
顶层的const无法和另一个没有顶层的const的参数区分,但底层的const可以区分
void f(int);
void f(const int); //重复声明,报错
void f(int *)
void f(int *const) //重复声明
void f1(int*);
void f1(const int*); //底层const,新函数。
void f1(int&);
void f1(const int&); //底层const,新函数。
3.3.2 重载与作用域
当在作用域内重复定义标识符,作用域内的标识符将会直接覆盖外部的标识符,包括重载的。
void f(int); //函数1
void f(char); //函数2
void f(double); //函数3
void foo(){
void f(double); //函数4
f(1.2); //正确调用函数4
f(1); //正确调用函数4,传入值为1.0
f('c') //错误,没定义
}
3.4 特殊用途语言特性
3.4.1 默认实参
可给函数的参数设置默认实参,但缺省的调用时,会默认赋值。
void f(int a,int b,int c=1,int d=2,int e=3); //声明
//调用
f(1,2); //实际为f(1,2,1,2,3);
f(1,2,3); //实际为f(1,2,3,2,3);
f(1,2,3,4,5); //实际为f(1,2,3,4,5);
设置默认实参只能从右到左,并且不能留空。
void f(int a=1,int b=2); //正确
void f(int a=1,int b); //错误
void f(int a,int b=1,int c); //错误
默认值可赋函数、变量或者表达式。
int x=1;
int v();
void f(int a=x,int b=v());
// 将在调用f时,调用v,为函数参数赋值
3.4.2 内联函数 inline
在函数的返回类型前面加上关键字inline,就可以将函数声明为内联函数。内联函数有点类似c的宏函数,它会在每一个调用的位置,内联的展开,从而节省函数调用和返回的开销。但内联函数声明只是向编译器发出的请求,编译器可以选择忽略。
inline void f();
内联函数定义通常放在头文件中
3.4.3 constexpr 函数
该函数相当于一个常量表达式。
constexpr int f();
constexpr 函数定义通常放在头文件中
3.5 调试帮助
3.5.1 assert 预处理宏
assert(expr);
当expr为假时输出信息并终止程序。
3.5.2 NDEBUG 预处理变量
当定义NDEBUG后,表示关闭调试。
自定义调试
#ifndef NDEBUG
//调试代码
#endif
对调试有帮助的标识符
- __func__ 当前函数名 字符串
- __FILE__ 文件名 字符串
- __LINE__ 当前行号 整型
- __TIME__ 编译时间 字符串
- __DATE__ 编译日期 字符串
c++语法拾遗,一些细节与特性的更多相关文章
- PHP 5.4语法改进与弃用特性
PHP 5.4于本月尘埃落定,它是 PHP 自 2009 年以来的首次重大更新.该版本对语言部分进行了增强,包括支持 Traits 和移除部分争议特性. Traits 同 Java 和 .NET 一样 ...
- .NET基础拾遗(6)特性
1 神马是特性?如何自定义一个特性? (1)特性是什么 特性是一个对象,可以加载到程序集及程序集的对象中,这些对象包括 程序集本身.模块.类.接口.结构.构造函数.方法.方法参数等,加载了特性 ...
- 关于ES6语法的 一些新的特性
1.新的变量声明 :let :块级作用域,解决全局污染问题 const :常量 ,如π:3.1415927 class :类 .var:弱类型 funciton :方法 , import : 导入参 ...
- [转载] C++11新特性
C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...
- Vue.js基础拾遗
本篇目录: 模版语法 插值 指令 v-bind指令 v-on指令 计算属性与侦听器 计算属性VS方法 计算属性VS侦听属性 Class与Style绑定 绑定HTML Class 绑定内联样式 条件渲染 ...
- [WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析
[WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析 标签: webkit内核JavaScriptCore 2015-03-26 23:26 2285 ...
- C#回顾 –6.特性
1.特性是什么? Attribute 用来对类.属性.方法等标注额外的信息,贴一个标签(附着物) 通俗:给 类 或 类成员 贴一个标签,就像航空部为你的行李贴一个标签一样 个人理解,特性就是修饰 ...
- Javascript之旅——第六站:看看writable特性
说起js中的那些特性标记,总觉得有些怪怪的,那为什么要说到这个attribute,起源于对一个问题的疑问,我们都知道window对象其实就是 浏览器窗口的一个实例,既然是一个实例,那这个实例就应该有“ ...
- (转)C++0x语言新特性一览
转自:http://blog.csdn.net/zwvista/article/details/2429781 原文请见http://en.wikipedia.org/wiki/C%2B%2B0x. ...
随机推荐
- MySQL 中如何归档数据
归档,在 MySQL 中,是一个相对高频的操作. 它通常涉及以下两个动作: 迁移.将数据从业务实例迁移到归档实例. 删除.从业务实例中删除已迁移的数据. 在处理类似需求时,都是开发童鞋提单给 DBA, ...
- php session 的使用方法
public function insert(Request $request){ $parm = $request->except('token'); $this->validate($ ...
- linux定时任务 - at定时任务
at命令是一次性定时计划任务,at的守护进程atd会以后台模式运行,检查作业队列来运行作业.atd守护进程会检查系统上的一个特殊目录来获取at命令的提交的作业,默认情况下,atd守护进程每60秒检查一 ...
- php 23种设计模型 - 适配器模式
适配器模式(Adapter) 适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁.这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能. 这种模式涉及到一个单一的类, ...
- C++ 接口的实现方式
一.接口的定义 有时候,我们得提供一些接口给别人使用.接口的作用,就是提供一个与其他系统交互的方法.其他系统无需了解你内部细节,并且也无法了解内部细节,只能通过你提供 给外部的接口来与你进行通信.根据 ...
- dotnet 委托的实现解析
缘起 最近被问到什么是.Net中的委托.问题虽然简单却无从回答.只能说委托是托管世界的函数指针,这么说没啥大毛病,但也都是毛病(当时自己也知道这么说不太对,不过自己不太爱用这个也没准备确实没有更好的答 ...
- JavaWeb——Http
4.1.什么是http http(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上. 文本:无链接 超文本:利用超链接将普通文本的信息组织在一起的超级文本 4.2.http两个时代的 ...
- linux下查看文件编码及修改编码介绍
1.在Vim中可以直接查看文件编码:set fileencoding即可显示文件编码格式.如果你只是想查看其它编码格式的文件或者想解决用Vim查看文件乱码的问题,那么你可以在~/.vimrc 文件中添 ...
- ZYNQ使用ymodem协议传输文件
SDK: V2014.4 协议: Ymodem 工具: USB转UART转接线.xshell6软件 可实现各种文件传输,大小不限,只是速度很慢 参考原代码如下: /****************** ...
- 生产环境频繁内存溢出,原来就是因为这个“String类”
摘要:如果在程序中创建了比较大的对象,并且我们基于这个大对象生成了一些其他的信息,此时,一定要释放和这个大对象的引用关系,否则,就会埋下内存溢出的隐患. 本文分享自华为云社区<[高并发]你敢信? ...