首页 > 编程语言 >C++ Primer 学习笔记 PartI C++基础

C++ Primer 学习笔记 PartI C++基础

时间:2024-02-04 22:36:45浏览次数:38  
标签:const 常量 int PartI C++ 引用 类型 Primer 指针

Ch1开始

这一章包含控制流,条件,循环,注释,标准IO等内容。

对于C语言/ACM C+STL中常见数值的内容不再赘述,仅总结较为不熟悉的内容。

Part I C++基础

CH2 变量和基本类型

2.1 基本内置类型

2.1.1 算术类型

image-20240202162430838

2.1.1 类型转换
  • 向unsigned赋超出范围的值,结果取余,对于signed,结果未定义。
  • 不要混用signed和unsigned。表达式中既有signed又有unsigned,当signed为负值时会出现异常结果,因为它会自动转换为unsigned。
2.1.3 字面值常量
  • 整型字面值:

    • 默认情况下,十进制为带符号数(int, long, long long),八进制和十六进制则都有可能(前三种加上uint,ull)。
    • 类型是能够容纳该数的有关类型中尺寸最小者,若超过所有类型的表示范围将发生错误。
    • short没有对应的字面值。
    • 十进制字面值中不含负号,负号的作用是取负值。
  • 字符串字面值:

    • 实质是常量字符构成的数组
    • 编译器在末尾自动添加空字符'\0',因此实际长度比内容多1
  • 转义序列

    image-20240202164454063

  • 通过前后缀指定字面值类型

    image-20240204151111329

  • 其他字面值: true false nullptr

2.2 变量

2.2.1 变量定义
  • 列表初始化,使用花括号。列表初始化如果存在丢失信息的风险,则编译器会报错。
  • 默认初始化:函数体外为0,函数体内为未定义。
2.2.2 变量定义与声明的关系

声明:使得名字为程序所知

定义:创建与名字关联的实体

分离式编译:详见2.6.3和6.1.3

extern int i;   //声明
int j;			//声明并定义 
2.2.3 标识符
2.2.4 名字的作用域

2.3 复合类型

2.3.1 引用
  • 引用即别名,本身不是一个对象。
  • 定义时必须初始化,初始值不能是字面值,应该是对象,且引用类型与被引用对象的类型一致。
2.3.2 指针
  • 指针本身是一个对象,也无须定义时初始化。
  • 使用解引用符(*)来操作对象。
  • 不能把int变量直接赋值给指针,即便值为0。
  • 建议初始化所有指针。
  • void*指针
    • 特殊指针类型,可存放任意对象的地址
    • 只能与其他指针比较,作为函数的输入输出,或者赋值给另一个void*指针
    • 不能直接操作void*指向的对象
  • 指向指针的引用
int i = 42;
int *p;
int *&r = p; //从右向左阅读,r表示指向指针的引用
r = &i;		//等价于p = &i
*r = 0;		//等价于*p = 0 

2.4 const 限定符

初始化和const

  • 默认状态下,const对象尽在当前文件内有效
  • 编译器在用到const变量处执行替换
  • 如要在多个文件之间共享const对象,必须在定义前加extern关键字
2.4.1 const的引用
  • 只能用对常量的引用来引用常量(引用的类型与所引用对象保持一致)

  • 引用的类型与所引用对象保持一致,但存在例外情况:初始化常量引用时允许用任意表达式作为初始值,如字面值和非常量,只要该表达式能够转换成引用的类型即可。

    int i = 42;
    const int &r1 = i; 	//ok
    const int &r2 = 42; //ok
    const int &r3 = r1 * 2; //ok
    int &r4 = r1 * 2; //wrong,非常量引用不能这么做
    

    实质上,此时编译器创建了一个对应类型的临时量,该临时量被常量引用绑定。

    常量引用仅对引用可参与的操作进行了限定,它可以引用非常量,但不能通过引用修改非常量的值。

2.4.2 指针和const

指针可以指向常量或非常量,指向常量的指针不能用于修改所指对象的值。

指针类型必须与其所指对象类型一直,但存在例外情况:允许一个指向常量的指针,指向一个非常量对象。利用与2.4.1相似。总得来说,可以认为const类型的指针和引用自认为指向了常量,自觉地不去改变所指对象的值。

const指针

由于指针本身是一个对象,允许把指针本身定为常量。

int errNumb = 0;
int *const curErr = &errNumb; // 指向非常量的常量指针。可以通过curErr修改errNumb
const double pi = 3.14;
const double *const pip = π //指向常量的常量指针。
//从右向左阅读,表示pip是常量对象,且为指针。该指针指向的对象为const double。
2.4.3 顶层const

顶层const表示指针本身是常量(更一般的,表示任意对象本身是常量),底层const表示所指对象是常量(与指针、引用等复合类型的基本类型有关)。

当执行对象的拷贝操作时,顶层const通常不受影响,而底层const却不能忽视要求拷入和拷出对象具有相同的底层const资格,或者数据类型能够转换。一般来说,非常量可以转换成常量,反之则不行。

2.4.4 constexpr 和 常量表达式

常量表达式

指在编译期间就得到计算结果的表达式。

const int N = 114514; // yes
const int M = N + 1;  // yes
int P = 998244353; 	  // no,因为类型是非常量
const int sz = size(); //no,因为编译期无法获取

constexpr

C++ 11 规定,允许将变量声明为constexpr类型以由编译器验证变量的值是否为常量表达式。

constexpr const int sz = size(); //只有当size()是constexpr函数时才正确

6.5.2节将深入介绍constexpr函数。

如果你认定一个表达式是常量表达式,就声明为constexpr。

字面值类型

容易得到值的类型。如算术类型,引用,指针。

非字面值类型:自定义类,IO库,string类型等。

指针和引用能够定义为constexpr,但初始值受严格限制。

指针和constexpr

constexpr把它所定义的对象置为了顶层const,与指针所指的对象无关

2.5 处理类型

2.5.1 类型别名

传统方法 typedef

typedef double wages;
typedef wages base, *p; //base是double的别名,p是*double的别名

新标准 别名声明

using SI = Sales_item;
2.5.2 auto类型说明符
  • 因为一条声明语句中只能有一个基本数据类型,因此该语句中所有变量初始基本数据类型必须一样。

    auto i = 0, *p = &i; 	//ok,相当于int i = 0, *p = &i;
    auto sz = 0, pi = 3.14;	//wrong
    
  • auto一般会忽略顶层const,而底层const被保留

    const int ci = i, &cr = ci;
    auto b = ci;	//b为int
    auto c = cr;	//c为int
    auto d = &i;	//d为int*
    auto e = &ci;	//e为(const int)*
    

    如果希望推断出的auto类型是顶层const,需要明确指出

    const auto f = ci; //ci的推演类型为int,f为const int
    

    还可以将引用类型设置为auto,这时原来的初始化规则仍适用

    auto &g = ci;	//ok
    auto &h = 42;	//wrong, 非常量引用不能绑定字面值
    const auto &j = 42; //ok,常量引用可以绑定字面值
    
2.5.3 decltype类型指示符

对于需要根据表达式推断类型,而不用该表达式初始化变量的情况,C++11引入了第二种类型说明符decltype

decltype(f()) sum = x; //sum的类型为f的返回类型

const int ci = 0, &cj = ci;
decltype(ci) x = 0; // const int x = 0;
decltype(cj) y = x; // const int &y = x;
decltype(cj) y; //错误,引用必须初始化

decltype与引用

有些时候表达式将向decltype返回引用。这种表达式通常可以作为一条复制语句的左值。

int i = 42, *p = &i, &r = i;
decltype(r + 0) b; //b是未初始化的int,因为r+0的结果是int型值
decltype(*p) c; //错误,c是int&,必须初始化

如*p, 表达式的内容是解引用操作,decltype的结果为int&。

与auto不同,decltype的结果形式与表达式形式密切相关,例如,当表达式被括号括起时,decltype的结果将为引用。

decltype((i)) d; //错误,d是int&,必须初始化
decltype(i) e;	 //正确,e是未初始化的int。

decltype((表达式))的结果永远为引用。当且仅当表达式结果为引用时,decltype(表达式)的结果为引用。

2.6 自定义数据结构

略。

预处理器概述

预处理器看到#include 标记时,用指定头文件的内容代替#include

此外,还有头文件保护符:

'#define' 把一个名字设置为预处理变量

'#ifdef' 当且仅当变量已定义时为真

'#ifndef' 当且仅当变量为定义时为真

一旦检查结果为真,则执行后续操作,直至遇到#endif为止。

使用这些功能能够有效防止重复包含的情况发生,因此最好习惯性地设置保护符,不管该文件是否被其他文件包含。

#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
struct Sales_data {
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
}
#endif

预处理变量无视C++语言中关于作用域的规则。

标签:const,常量,int,PartI,C++,引用,类型,Primer,指针
From: https://www.cnblogs.com/vv123/p/18007107

相关文章

  • C++中promise和future初认识
    future/promisefuture提供了一个基于数据(future模板类型)的异步概念:对于一个类型T,可以在以后通过get接口获得这个类型T的变量。或者打个不太恰当的比方,当你获得一个future对象时,就获得了一个消费券(consumer):拿着这张券可以兑换(get)一个T类型的结果(如果数据未就绪的话会阻塞等......
  • C++多线程 第三章 在线程间共享数据
    第三章在线程间共享数据共享数据基本问题如果所有共享数据都只读,那就没有问题.不变量(invariants):对特定数据结构总为真的语句.例如:"该变量表示线程数量."修改线程之间共享数据的一个常见潜在问题就是破坏不变量.竞争条件(racecondition):线程竞争执行各自的操作,导......
  • C++之INI配置文件读写/注释库 inicpp 介绍【简单易用-包含inicpp.hpp头文件即可】
    一个头文件(header-file-only)搞定INI文件读写、甚至进行注释。跨平台,并且用法极其简单。MITlicense,从此配置INI文件就像喝水。【注:对您有帮助的话,Star或Issues为项目维护提供动力,感谢。】-byofficalofJN-inicppproject.一、库下载https://github.com/dujingning/inicpp......
  • 14. C++函数的编译
    C++函数的编译C++和C语言的编译方式不同。C语言中的函数在编译时名字不变,或者只是简单的加一个下划线_(不同的编译器有不同的实现),例如,func()编译后为func()或_func()。而C++中的函数在编译时会根据它所在的命名空间、它所属的类、以及它的参数列表(也叫参数签名)等信息进行重新......
  • 创建大量栅格文件并分别写入像元数据:C++ GDAL代码实现
      本文介绍基于C++语言GDAL库,批量创建大量栅格遥感影像文件,并将数据批量写入其中的方法。  首先,我们来明确一下本文所需实现的需求。已知我们对大量遥感影像进行了批量读取与数据处理操作——具体过程可以参考文章C++GDAL提取多时相遥感影像中像素随时间变化的数值数组;而随......
  • A Knight's JourneyC++
    题目看半天看不懂。題目把我恶心坏了。看网上说按字典顺序输出,到底是什么意思半天没搞懂。#include<iostream>#include<string>usingnamespacestd;intd[8][2]={{-1,-2},{1,-2},{-2,-1},{2,-1},{-2,1},{2,1},{-1,2},{1,2}};intvisit[8][8]={0};boolDFS(i......
  • CLion 2023: 一款专注于性能和效率的C/C++ IDE mac/win版
    JetBrainsCLion2023是一款专为C和C++开发人员打造的强大集成开发环境。这个版本致力于提供卓越的性能、强大的功能和一流的智能代码编辑支持,帮助您更高效地开发高质量的C和C++应用程序。→→↓↓载CLion2023mac+win版首先,CLion2023提供了对最新C和C++标准的全面支持。无论......
  • CF1454F Array Partition 题解
    题目链接:CF或者洛谷感觉很多人写太复杂了,其实感觉这题性质很好的。。询问是否可以分为三段\(max_1=min_2=max_3\)。考虑枚举\(max_1\),由于后缀\(max_3\)具有单调性,所以我们可以双指针轻松拿到这样一个模型:因为后缀\(max\)具有单调性,通过双指针我们可以拿到\(j\)后缀......
  • c++20模块化编程与传统区别
    传统:main.cpp+a.cpp(存放定义)+a.h(存放声明)c++20:main.cpp+a.cppm(存放定义,在定义前面写export即可)模块化编程好处:不再需要修改了函数到对应修改声明,两头跑编译更快,模块只在修改后才重新编译模块化编程举例://my_module.cppmimport<iostream>;exportm......
  • Find The MultipleC++
    这题就是找N的倍数m,M要求是由1和0组成且非0。可以用图来看,从1出发临边是1和0,然后广度遍历,第一个能能整除N的数输出就行。#include<iostream>#include<queue>usingnamespacestd;intmain(){intn=-1;while(cin>>n){if(n==0)break;longlon......