C++ Primer(英语第5版) 阅读日记 - 20200417 我终于搞懂了cpp指针和常量的定义

前言

第二章有点长的,今天继续加油吧。

const Qualifier(限定符)

在变量声明之前,加上const限定符可以防止他被将来不可预料的修改(被你的同事.jpg)。

const int bufSize = 512;

并且,在初始化的时候,他必须被显式地初始化。并且,除了不可修改以外,const限定的变量和原来的type表现形式是一致的。

int i = 42;
const int ci = i;
int j = ci;

const限定的整数在编译的时候,就已经hard code了。这点系统学过OS比较好理解。正因为如此,在编译不同文件时,const限定常量会被多次初始化。如果我们想在一个文件内定义,其他文件去使用他,就需要用到extern了。

// in file_1.cc
extern const int bufSize = fcn();
// in file_1.h
extern const int bufSize; // same bufSisze as defined in file_1.cc

回顾definition和declaration的区别:define多见于.c文件,实现功能;而declaration多见于.h文件,用于声明变量名称。但const限定符下的常量,我们必须在declaration时候就define,无法做到分离。

const & reference

我们如何引用常量?

const int ci = 1024;
const int &r1 = ci; // ok
r1 = 42; // error: r1 是常量引用,修改无用
int &r2 = ci; // error: 不行,常量必须使用常量引用

可以bind a const reference to

  • a nonconst object
  • a literal
  • a more general expression
int i = 42;
const int &r1 = i;
const int &r2 = 42; // reference to a literal
const int &r3 = r1 * 2; // reference to a nonconst variable
int &r4 = r * 2; // error: r4 is a plain, non const reference

Const reference may refer to a non-const object. Const reference和引用的的object无关,只限定了我们对他的行为。

Nonconst reference 指向 conference是illegal的。

Pointers 和 const

A pointer 可以指向const或者是nonconst。

const double pi = 3.14; // pi is const;
double *ptr = &pil; // error: ptr is a plain pointer
const double *cptr = π // ok: cptr 需要指向一个const double,不是const不能指,这里可以和之前一样从右往左理解
*cptr = 42; // error
double dval = 3.14;
cptr = &dval; // ok: but cannot change dval through cptr

接下来看一个骚操作,理解一下从右往左的指针:

// Example 1: const pointer
int errNumb = 0;
int *const cirErr = &errNumb; // 这是一个常量指针,一直指向errNumb
// Exapmle 2: const pointer of a const
const double pi = 3.14159;
const double *const pip = π // 这是一个常量指针,一直指向常量pi

这里最后一个还是从近到远理解:

  • pip 我定义了一个变量叫做pip
  • const pip 我定义了一个常量pip
  • *const pip 我定义了一个常量pip,他是一个指针:pip是一个常量指针
  • double *const pip 我定义了一个常量指针pip,他指向double
  • const double *const pip 我定义了一个常量指针pip,他指向常量double
  • const double *const pip = π 我定义了一个常量,所以必须初始化;他是一个指向常量double的指针,所以我必须分配一个常量double的地址给他。

当指针自身为const时,我们称之为top-level const
当指针指向的内容为常量时,我们称之为low-level const

When copy an object, top-level ocnsts are ignored. Low-level const is never ignored.

constexpr and Constant Expressions

A const expression is an expresssion whose value cannot change and that can be evaluated at compile time.

  • A literal is a constant expression.
  • A const object that is intialized from a const expression is a const expression.
    object是否为const expression取决于他的type和intializers。
const int max_files = 20; // yes
const int limit = max_files + 1; // yes
int staff_size = 27; // no: type not const
const int sz = get_size(); // no: initializer not const

实际上,在真实coding的时候,我们可以让编译器去辅助判断:constexpr去判断我们变量对应的initiailizer是否为const expression。

constexpr int mf = 20;
constexpr int limit = mf + 1;
constexpr int sz = size(); // ok only if size is a constexpr function

Pointers and constexper

constexpr imposes a top-level const on the objects it defines.

const int *p = nullptr; // p is a pointer to a const int
constexpr int *q = nullptr; // q is a const pointer to int

其实这里,我对于const与constexpr作用没有很好的理解:感觉constexpr有点多余。我查询了其他博客,这篇博客提出一些观念:

  • 是一种很强的约束,更好地保证程序的正确语义不被破坏。
  • 编译器可以在编译期对constexpr的代码进行非常大的优化,比如将用到的- - constexpr表达式都直接替换成最终结果等。
  • 相比宏来说,没有额外的开销,但更安全可靠。

你可能感兴趣的:(C++)