Const Qualifier

2022/2/12 23:48:13

本文主要是介绍Const Qualifier,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 

Initialization and const


1.Because we can't change the value of a const obeject after we create it, it must be initialized.

  • We may use only those operations that cannot change an object.
  int i = 42;
  const int ci = i;  // ok:the value in i is copied int ci
  int j = ci;  // ok: the value in ci is copied into j

 
2.When a const object is initialized from a compile-time constant, the compiler will usually replace uses of the variable with its corresponding value during compilation.

  const int bufSize = 512;  
  // the compiler will generate code using the value 512 in the places that our code uses bufSize.

 
3.To define a single instance of a const variable, we use the keyword extern on both its definition and declarations.

  • By default, const objects are local to a file.
  • When we define a const with the same name in multiple files, it is as if we had written definitions for separate variables in each files.
  // file_1.cc defines and initializes a constthat is accesable to other files
  extern const in bufSize = fcn();
  // file_1.h
  extern const in bufSize;  // same bufSize as defined in file_1.cc

 

Initialization and References to const


1.We use a reference to const, which is a reference that refers to a const type.

Term: const Reference is a Reference to const

C++ programmers tend to abbreviate the phrase "reference to cosnt" as "const reference".
Technically speaking, there are no const reference. A reference is not an object, so we cannot make a reference itself const.

  const in ci = 1024;
  const int &r1 = ci;  // ok: both refernce and underlying object are const.
  r1 = 42;  // error: r1 is a reference to const
  int &r2 = ci;  // error: nonconst refernce to a const object
  • Binding a reference to const to an object says nothing about whether the underlying object itself is const.
  int i = 42  
  int &r1 = i;  // r1 bound to i 
  const int &r2 = i;  // r2 also bound to i; but cannot be used to change i 
  r1 = 0;  // r2 is not const; i is now 0
  r2 = 0;  // error: r2 is a reference to const

 
2.With one exception of two, we can initialize a reference to const from any expression that can be converted to the type of the reference.

  • We can bind a reference to const to a nonconst object, a literal, or a more general expression.
  int i = 42;
  const int &r1 = i;  // we can bind a const int& to a plain int object
  const int &r2 = 42;  // ok: r1 is a reference to const
  const int &r3 = r1 * 2;  // ok: r3 is reference to const
  int &r4 = r * 2;  // error: r4 is a plain, nonconst reference
  • We can bind a reference to const to an object of a different type.
  double dval = 3.14;
  const int &ri = dval;
  // the compiler transforms this code into something like

  const int tem = dval;  // create a temporary const int from the double
  const int &ri = temp;  // bind ri to that temporary

  // If ri weren't const, we could assign to ri. 
  // Doing so would change the object to which ri is bound.
  // That object is a temporary, not dval.

 

By default, a reference may be bound only to an object, not to a literal or to the result of a more general expressions.
The type of a reference and the object to which the reference refers must match exactly.

  int &refVal4 = 10;  // error: initializer must be an object
  double dval = 3.14;
  int &refVal5 = dval;  // error: initializer must be an in object
Term: What is an Object?

In this book, we'll follow the more general usage that an object is a region of memory that has a type.

 

Pinters and const


1.Like a reference to const, a pointer to const says nothing about whether the object to which the pointer points is const.

Debuggign with reference to const and pointer to const
  #include<iostream>
  using namespace std;

  int main() {
    int a = 4;

    const int& q1 = a;
    int& q2 = a;

    q1 = 10;  // error: expression must be a modifiable lvalue.
    q2 = 10;

    const int* p1 = &a;
    int* p2 = &a;

    *p1 = 10;  // error: expression must be a modifiable lvalue.
    *p2 = 10;

    cout << "q1 = " << q1 << endl;
    cout << "q2 = " << q2 << endl;
    cout << "p1 = " << *p1 << endl;
    cout << "p2 = " << *p2 << endl;

  // output:
  // q1 = 10
  // q2 = 10
  // p1 = 10
  // p2 = 10
}
 
Pointers:

Unlike reference, a pointer is an object in its own right.
Pointers can be assigned and copied.
By default, the types of the pointer and the object to which it points must match.

  double dval;
  double *pd = &dval;  // ok: initializer is the address of a double
  double *pd2 = pd;  // ok: initializer is a pointer to double
  int *pi = pd;  // error: types of pi and pd differ
  pi = &dval;  // error: assigning the address of a double to a pointer to int 

 
2.Like any other const object, a const pointer must be initialized, and once initialized, its value( the address that it holds )may not be changed.
 

Top-level const


1.The distinction between top-level (the pointer itself is a const) and low-level (a pointer can poin to a const obj) matters when we copy an object.

  int i = 0;
  int *const p1 = &i;  // we can't change the value of p1; const is top-level
  const int ci = 42;  // we can't change ci; const is top-level
  const int *p2 = &ci;  // we can change p2; const is low-level
  const int *const p3 = p2; // right-most const is top-level, left-most is not
  const int &r = ci;  // const in reference types is always low-level
  • When we copy an object, top-level consts are ignored.
  i = ci;  // ok: copying the value of ci; top-level const in ci is ignored
  p2 = p3;  // ok: pointed-to type matches; top-level const in p3 is ignored
  • On the other hand, low-level const is never ignored. In general, we can convert a nonconst to const but not the other way round.
  int *p = p3;  // error: p3 has a low-level const but p doesn't
  int &r = ci;  // error: can't bind an ordinary int& to a const int object
  p2 = p3;  // ok: p2 has the same low-level cont qualification as p3
  p2 = &i;  // ok: we can convert int* to const int*
  const int &r2 = i;  // ok: can bind const int& to plain int   

 

Constexpr and Constant Expressions


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

  • Constexpr variables
  const int limit = max_files + 1;  // limit is a constant expression
  const int sz = get_size();  // sz is not a contant expression (initialized at run time)
  • Such expressions can be used as non-tpye template arguments, array sizes, and in other contexts that require constant expressions. (by "constant expressions" at cppreference.com)
  int n = 1;
  std::array<int, n> a1;  // error: n is not a constant expression
  const int cn = 2;
  std::array<int, cn> a2;  // ok: cn is a constant expression

 
2.Literal types are the types of constexpr variables and they can be constructed, manipulated, and returned from constexpr functions. (by "Literal types" at cppreference.com)
 
3.Constexpr imposes a top-level const on the objects it defines.

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


这篇关于Const Qualifier的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程