c++拾遗
创始人
2024-06-02 19:31:08
0

constexpr

对const对比,const的值允许在运行后确定,但是constexpr不允许

const int a = get_sz();
constexpr int b = get_sz(); // 如果get_sz()不是constexpr函数,则编译出错

auto与decltype

  • 普通的auto会忽略顶层const和引用
  • auto&会保留顶层const,auto&a = 42(推断为int&)是错的,前面要加const得到 const int&
  • decltype会保留顶层和底层const和引用
  • decltype(*p)得到的是引用类型
  • decltype((expr))永远都是引用类型

类型转换

数组转换

  • decltype不会将数组转换为首元素的指针,故其得到的类型为数组
  • sizeof也不会把数组转换为首元素的指针,故得到的为整个数组大小(字节为单位)

指针转换

  • 0或字面值nullptr能转换为任意指针类型
  • 任意非常量指针能转换void*
  • 对象指针能转换为const void*

类类型转换

比如将字符串赋值给string,由编译器自动执行,但是不能多次

强制类型转换

static_cast<>()

常用于将void*转换成本来的指针类型(由开发者自己保证类型是正确的,否则是未定义的),或者用于基本类型之间的转换

const_cast

  • 只能改变底层const(底层指的是指针指向一个常量,顶层指的是指针本身是常量)
  • 不能用于类型转换,其他转换不能改变const属性

reinterpret_cast

基于更加底层的位模式转换,依赖于机器,应当尽可能避免,其无视任何限制

函数

数组形参

指针式传递

这种方式,编译器把数组当成指针

void print(const int* p);
void print(const int p[]);
void print(const int p[10]); // 10仅仅是我们期望的,编译器会忽略,均等效与const int*

引用式传递

void print(int & a[10]); // error,这代表数组是10个int 引用,这个不符合语法会编译错误
void print(int (&a)[10]); // ok, a是引用一个大小为10的数组,注意此时,10会被编译器考虑

务必小心括号问题,少括号会产生另外一种语义

void print(int * matrix[10]); // 等效于int ** matrix
void print(int (*matrix)[10]);// 指向一个含有10个元素的数组, 10会被考虑 int (*)[10]
void print(int matrix[][10]);// 与上面等效

重载和const形参

  • 编译器无法区分有无顶层const,所以常量和顶层const无法同时存在
  • 但底层const(指针或者引用)可以重载,编译器优先把非常量传给非const重载版本

函数指针

  • 当为形参的时候,函数类型会被自动转换为函数指针
  • 当作为函数指针的时候,函数类型不会被转换为函数指针,c++不允许返回函数类型
void demo(int, int);
using decltype(demo) = Func; // Func是函数类型
using decltype(demo)* = FuncPointer;// 指针类型
Func f(Func g); // error
Func* f(Func g); FuncPointer f(Func g); // ok, 形参里的Func会被转换为函数指针

关键字

  • mutable 允许在const成员函数里面修改变量

前向声明

class A;
class B
{A a; // errorB b; // errorA& c; // okA* d;// ok;static B e; // okstatic A f; // ok
};

友元说明

注意类里面的友元说明仅仅是声明了访问权限,即便友元函数定义在类内部,也必须在外部声明,否则即便是类的成员函数也无法访问

class A
{
public:friend void f(){cout << "f was called!\n"};void gg(){f();} // error, f还未被声明void hh();
};
void f();
void A::hh(){f();} // ok

静态类成员

  • 必须在外部声明类静态成员变量,否则无法使用,类外声明是无需再写static关键字,但数据类型要写如 int A::w = 10;
  • 若想在类内初始化类内静态变量,必须将其声明为常量const/constexpr
  • 对于在类内提供初值的常量静态成员变量,我们也应该在类外声明一下(但不要提供初值)

delete声明符作用与析构函数

此时只能使用new创建对象,且无法delete释放

构造/析构函数调用虚函数

  • 可以理解为虚机制失效,由构造/析构函数所属类确定
  • 因为基类构造先于派生类构造,派生类析构先于基类构造执行

使用using继承构造函数

using可以指示编译器“继承”基类构造函数,这里不是真正的基础,而有编译器自动生成一些构造函数,这些构造函数与基类构造函数有相同的参数列表,如下

derived(pargram):base(pargram)
  • using不会继承默认、拷贝、移动构造函数

  • 对于含有默认参数的基类构造函数,则会生成多个构造函数,每个构造函数形参数量从最多,依次递减到非默认参数数量

    如基类构造函数有两个参数,一个默认,则会生成接受两个参数的和接受左边那个参数的两个构造函数

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...