c++premier(第五版)读书笔记-第二章

C++11支持变量的列表初始化。即

int a{11};

当用于内置类型的变量时,这种初始化形式有一种重要特点:
如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器将报错。
示例

定义在函数体内部的内置类型如果不被显示初始化,那么他就不会被初始化。
定义在函数体外的内置类型变量被赋予一个特定的值

定义在函数体内部的则不被初始化

因为引用不是一个对象,所以不存在引用的引用与引用的指针;但是指针存在指针的指针与指针的引用。
指针的引用定义模式为

int *&p;

要了解p的类型是什么,最简单的办法是从右向左阅读r的定义。离变量名最近的符号对变量的类型有最直接的影响

一个引用一旦初始化后,它即与某个对象产生了绑定关系,该绑定关系不能解除,不能更换。

在默认状态下,const对象仅在文件内有效,因此需要使用extern关键字,在相应的头文件内使用extern关键字声明,在相应的cpp中进行定义与赋值。

extern const int x;
//head.h
extern const int x = 1;
//head.cpp

常量引用是指对const的引用
部分代码如下。

int i=42;
const int &r1=i;
const int &r2=42;
const int &r3=r1*2;
//该处的代码实际上是两行代码
//const int tmp=r1*2;
//const int &r3=tmp;
//即r3绑定了一个临时对象,这种写法是正确的
int &r4=r1*2
//该处代码发生错误,由于r4不是常量,那么就意味着可以对其指向的对象赋值
//但其指向的是一个被const修饰的临时对象
//const不能被修改。
//因而该句被c++视为错误

对const的引用仅仅表示无法通过引用来修改const的值,但不代表无法通过其他方法修改

#include<iostream>
using namespace std;
int main()
{
    int i = 42;
    int &r1 = i;
    const int &r2 = i;
    r1 = 0;
    cout << i << r2;
    return 0;
}
//输出00,const的值被修改了

相同的指针对于const也有类似的操作,但是指针不支持如下的操作(存疑)

const int i=1;
const int i2=i*2;

原文:试试这样想吧,所谓指向常量的指针或引用,不过是指针或引用“自以为是”罢了,他们觉得自己指向了常亮,所以自觉地不去改变所指对象的值。

指针本身是可以被定义为const的。把*放在const之前,这种写法的意味是该指针指向的位置是不变的。但其指向的值是可以改变的。

用顶层const表示任意的对象(如int string 指针)是常量,底层const则表示指针或引用指向的对象是常量。

int i=0;
int *const p1=&i;//不能改变p1的值,是一个顶层const
const int ci=42;//不能改变ci的值,是一个顶层const
const int *p2=&ci;//允许改变p2的值,这是一个底层const
const int *const p3=p2;//靠右的const是顶层const,靠左的是底层const
const int &r=ci;//用于声明引用的const都是底层const

当进行对象的拷贝工作时,拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。一般来说,非常量可以转换为常量,反之不行。

int *p=p3;//错误,p3包含底层const定义,p没有
p2=p3;//正确:p2与p3都是底层const
p2=&i;//正确,int *能转换为const int*
int &r=ci;//错误:普通的int &不能绑定到int常量上
const int &r2=i;//正确:const int&可以绑定到一个普通int

constexpr与常量表达式

常量表达式是指值不会改变并且在编译过程中就能得到计算结果的表达式,例如

const int x=1;

c++11提出了新的标准constexpr,用于指定一个常量表达式,代替const。
使用

constexpr int m=1;//直接使用字面值
constexpr int x(int y);//声明一个的constexpr修饰的函数
constexpr n=x(2);//调用函数,初始化constexpr

auto关键字可以自行推断变量的类型(不一定准确)
auto一般会忽略顶层的const,保留底层const

希望从一个表达式的类型推断出要定义的变量的类型,但是不想用该表达式的值初始化变量。为了满足这一要求,c++11引入了decltype。

decltype(f()) sum=x;//sum的类型就是函数f的返回类型

如果decltype使用的表达式是一个变量,则decltype返回该变量的类型(包括顶层const与引用在内)

const int ci=0,&cj=ci;
decltype (ci) x=0;//x的类型是const int
decltype (cj) y=x;//y的类型是const int&,y绑定到变量X
decltype (cj) z;//错误,Z是一个引用,必须初始化

如果decltype使用的表达式不是一个变量,则返回表达式结果对应的类型

int i=42,*p=&i,&r=i;
decltype(r+0) b;//加法的结果是int,b是一个(为初始化的)int
decltype(*p) c;//错误:c是int&,必须初始化
//表达式的内容是解引用操作,则decltype将得到指针所指的对象

//为表达式加上了一层括号或多层括号,编译器会认为这是一个表达式。
//变量是一种可以作为赋值语句左值的特殊表达式,因而decltype可以得到引用类型
decltype((i)) d;//得到int&,必须初始化,错误
decltype(i)e;//得到为初始化int

c++11中加入了类内初始值。

class myclass
{
private:
    int n = 22;
public:
    myclass() = default;
    void print()
    {
        cout << n;
    }
};
//n在默认构造函数中没有被初始化,最终值为22;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值