C++ 新/冷用法集锦 (一)

C++其实有许多的新奇或者冷用法,经过本人整理,给大家普及一下

1.位域结构体

结构体里的成员竟然有个冒号,例如下面的节选代码

struct BitField
   {
      unsigned int a:4;  //占用4个二进制位;
      unsigned int  :0;  //空位域,自动置0;
      unsigned int b:4;  //占用4个二进制位,从下一个存储单元开始存放;
      unsigned int c:4;  //占用4个二进制位;
      unsigned int d:5;  //占用5个二进制位,剩余的4个bit不够存储4个bit的数据,从下一个存储单元开始存放;
      unsigned int  :0;  //空位域,自动置0;
      unsigned int e:4;  //占用4个二进制位,从这个存储单元开始存放;
   };

位域可以设置成员的二进制位置,对于节省内存是特别好的。
具体用法可以去网上进一步了解。

2.反斜线可以实现多行宏/注释

这个很多人都知道,宏或注释的最后加一个反斜线\,可以多续一行:

#define exitif(cond) do{\
				   if(cond)\
				       exit(0);	\
	             }while(0)
	//注意:反斜线必须是最后一个字符\
	                          才行;\
	                          最后一行不用加

3.标识符中可以使用$

这个当做冷知识吧,不要多用,毕竟兼容性不是很好。

int var$1 = 5;
int $var1=5;
int var1$ = 5;
cout<<var$1<<endl;
cout<<$var1<<endl;
cout<<var1$<<endl;

有些编译器还不支持。

4.lambda表达式(C++11)

lambda表达式又称匿名函数,可以直接当成函数变量使用。
可以使用auto来存储它。
例如:

auto func = [](int a) -> int { return a*a; }
cout<<"5*5="<<func(5)<<endl;

语法形式:

[函数对象参数可以为空] (函数参数) mutable 或 exception 声明可以不加 -> 返回值类型可以不加 { 函数体若无return则自动判定为void函数 }

看下面几个例子就懂了:

[] (int x) {return x*x;}
[] (int& a) { return ++a; }
[] { g_score++; }	//无参数时小括号可以省略

至于中括号内、mutable等的用法可以取网上查都有的。

另外,C++14还支持泛型lambda,参数类型可以是auto!

5.__noop

这个类似关键字的东西的作用是,可以当成一个接受任何类型任何个数参数的函数名,而且什么也不干。它和下面这个一个道理:

void UselessFunction(...)
{}

可以用于调试:

#ifdef DEBUG
#define PRINT printf
#else	//不调试的时候不输出
#define PRINT __noop
#endif

注意是两个下划线.

6.#include_next

这个是GNU扩展,有些编译器不能用的
它的作用是,找第二个符合名字目录及子目录下的头文件。
尽量不要用,除非真的不太行
可以参考
https://blog.csdn.net/qq_17291647/article/details/103572863

7.新的强制转换

C++为了分类强制转换,新添四个强制转换关键字,分别是static_cast、dynamic_cast、const_cast和reinterpret_cast。
它们的作用如下:
参考 https://www.cnblogs.com/chenyangchun/p/6795923.html

关键字安全性作用
static_cast①普通类型转换 ②基类子类指针/引用转换(最好向上)③void* 转成type* ④type 转成const type
dynamic_cast较高基类子类的上下转换(可以向下,更为安全)
const_cast较高去掉const!! (指针也可)
reinterpret_cast极低仅仅是二进制操作,把指针转成数字。。!

8.新的for循环(C++11)

这么好用的for循环怎么能错过呢!

std::vector<int> numbers {0,1,2,3};
for(const auto&i : numbers)
    std::cout<<i<<" ";

格式:
for(type 元素 : 容器)
{操作}

其中的type:
①只读:auto / const auto& 【std::set只能用只读】
②可改:auto&

std::for_each也是不错的:

std::vector<int> numbers {0,1,2,3};
std::for_each(numbers.begin(),numbers.end(),
   [](auto ele)	//注意:这是一个lambda表达式
   {
      std::cout<<ele<<" ";
   }
   );

9.“双非” (!!)

这个操作并非多此一举(其实还是没用)
它的用途就是把int转成bool.(更加标准。。)
库函数竟然也用到了:

//from assert.h ---↓line64
#ifdef NDEBUG
#define assert(_Expression) ((void)0)
#else /* !defined (NDEBUG) */
#if defined(_UNICODE) || defined(UNICODE)
#define assert(_Expression) \
 (void) \
 ((!!(_Expression)) || /*←这里*/\
  (_wassert(_CRT_WIDE(#_Expression),_CRT_WIDE(__FILE__),__LINE__),0))
#else /* not unicode */
#define assert(_Expression) \
 (void) \
 ((!!(_Expression)) || /*←这里*/\
  (_assert(#_Expression,__FILE__,__LINE__),0))
#endif /* _UNICODE||UNICODE */
#endif /* !defined (NDEBUG) */

说明编写者也想到了这个奇葩用法。

10.获取变量的类型名称字符串

用到的关键字 (这是一个受头文件限制的操作符)typeid.
注意: 需要包含头文件< typeinfo > ,否则编译器会找上门来:

[Error] must #include < typeinfo > before using typeid

示例:

int a=1;
double f=6.0;
string s="Rico";
cout<<"type of a:"<<typeid(a).name()<<endl;
cout<<"type of f:"<<typeid(f).name()<<endl;
cout<<"type of s:"<<typeid(s).name()<<endl;

输出竟然不太好:

type of a:i
type of f:d
type of s:Ss

说明这种方法确实有用,但不是很稳定——能少用就少用。
真的要用的话只能特判

if(typeid(a)==typeid(int))	//准行
    cout<<"int";

【未完待续】

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值