C++:const

const

constIs a powerful C ++ keywords provided by constthe use of very large, but in general, constthe role of only one: to ensure that the modified content will not be modified by the program.

const basic usage

Use a type of object constmodification that is limited to the object is read-only and can not be modified to operate, because the operation can not be modified, which also requires us to declare constmust be assigned or initialized when the object simultaneously. const object initialization is generally of the form:

const TypeName Var = Expression;

Example:

const int a = 0;
int const a = 0; // 等价写法
a = 1; // 编译报错

It may be noted that the initialization expression const object is initialized, just load our example using a constant expression. In fact, const initialization can be in the form:

int getA() {
    return 0;
}
const int a = 0; // 字面量0是常量表达式,在编译期就能确定,a在编译期完成初始化
const int b = getA(); // getA()在编译期编译,b在运行时初始化

A special case is expected this constobject exists in the global scope, you can add a statement at the time of externmodification, then you can not assign the initial statement, but the program must ensure that at least one declared initial value.

// A.cpp
extern const int a;

// B.cpp
extern const int a = 0;

const reference

const reference is a reference to const object, that is, it just make sure not to modify the referenced content, whether the object is referenced constobjects unrelated.

int a = 0;
const int b = 0;
const int &c = a; // 正确,可以直接修改a的值,但不能通过c修改a
const int &d = b; // 正确,b、d均不可修改

It should be noted that bind to a const reference to a temporary object is illegal.

int a = 0;
const int &b = a + 1; // 这里a+1生成了一个临时对象
//等价于
const int temp1 = a + 1;
const int &b = temp1;

const double &c = a; // 这里通过隐式类型转换生成了临时对象
// 等价于
const double temp = a;
const double &c = temp;

Although it can compile, but this is a reference to meaningless binding.

const pointer

const pointer can also be modified. Because of the multi-stage pointer, combined with const also becomes complicated.

int a = 0;
const int b = 0;

const int *c = &a; // 合法,c是一个指向常量的指针,尽管a本身不是常量
// 等价于
int const *c = &a;

const int *d = &b; // 合法,b是常量,c是指向常量的指针
int *e = &b; // 非法,b是常量,普通指针无法指向常量地址
const int *f = &b; // 合法,b是常量,f是指向常量的指针

The most common is a constant pointer and a pointer to a constant , the former is a pointer indicating a constant, i.e. can not be modified at the address, which represents the contents stored at the address is a constant. And a pointer to pointer constant is constant constin both cases of a modified pointer, in the "C ++ Primer" book, both are called top const and bottom const .

const int a = 0;
const int *b = &a; // b是指向常量的指针,底层const
int c = 0;
int * const d = &c; // d是一个常量指针,顶层const
const int * const e = &a; // e是一个指向常量的常量指针

When it comes to multi-level pointer, you can read the statement from right to left expression, confirming constmodified what level.

int a = 0;
int *b = &a; // b是一个一级指针
int **c = &b; // c是一个二级指针
int **const *d = &c; // d是一个三级指针
/* 
从右往左阅读表达式:
1.首先声明了一个变量d
2.下一个是*,说明d是一个指针,它指向了一个对象
3.接着是const,说明它指向的这个对象不能修改
4.接着又是一个*,说明指向的对象也是一个指针
5.然后是最后的*,说明指向的指针指向的对象仍是一个指针
6.最后是int,说明最后一级指针指向的是一个int类型的地址
在理解这个声明之后很容易就可以对下面的赋值做判断
*/
d = &c; // 正确,d是一个普通指针
*d = &b; // 错误,解引用d得到的是一个常量对象
**d = &a; // 正确,二次解引用d得到的是一个普通指针

constexpr expression

As mentioned earlier, it may be constant expression or constant expression object is initialized const. The so-called constant expression refers to expression at compile results can be obtained by the constant expression initialized const objects can also be involved in the composition of constant expressions. At some point, we hope to be able to get an expression determined at compile time, but confirmed that an object in a complex project in a constant expression is not very difficult, thus introducing a C ++ constexprkeyword explicit instructions for a object is a constant expression.

constexpr int a = 0; // 正确,用字面量0初始化常量表达式
constexpr int b = getB(); // 正确与否取决于getB()是否是常量表达式

Due to the need to determine the value of constexpr object at compile time, which means the initialization of pointers and references constexpr proposed more stringent requirements: Under normal circumstances, define the address of the object inside the function can not be determined at compile time, so as not to initialize the value of the constant expression, on the contrary, the global object can.

const and function

constParameter function may be modified.

int LiF(const int lif);
// 正确,在函数内部不能修改lif
// 当然,形参本身只是一个拷贝,在函数调用过程中发生的修改并不会反馈到实参
int LiF(const int *lif);
// 正确,保护原数据不被修改
int LiF(const int &lif);
// 正确,这是最常用的写法,兼具效率与安全性

constYou can also modify the return value of the function. constEnsure that the return value of the function is not modified, it can not be used as an lvalue.

const int& LiF(int &lif) {
    return lif;
}

const and class

constCan be modified class members , due to call the constructor has confirmed the contents of the object, that is, const member needs to be initialized before the constructor, then, can only be modified by a class member initialization list to initialize.

class LiF {
public:
    LiF(int _lif): lif(_lif) {}
private:
    const int lif;
};

const can be modified class member functions , member functions are modified often called member function, often a member function can be called all objects, but often the object can only call regular member functions. This is because the member function parameter list in an implicit pass a thispointer, with constmodifications member function actually modified this, but const *there is no way to convert an ordinary pointer type, so you can not call an ordinary member functions. Also, because the function overloading will not ignore the underlying const, so the function of the members constmay be configured overloaded. Objects will find very ordinary member functions through an exact match, and often the object will be matched to the corresponding member function normally.

class LiF {
public:
    int get() { return lif; }
    int get() const { return lif; } // 常成员函数重载
private:
    int lif;
};

LiF l1;
const LiF l2;
l1.get(); // 调用的是int get();
l2.get(); // 调用的是int get() const;

Sometimes we hope that members of the class can record certain information, even within a const object. Then you need to always be a member variable, correspondingly, C ++ provides mutablekeyword.

class LiF {
public:
    void count() const {
        lif++;
    }
private:
    mutable int lif;
};

LiF l1;
const LiF l2 = l1;
l2.count();

constIt can also be modified member function's return value, and const ordinary function's return value similar to prohibit chained calls, or prohibiting the return value becomes the left value.

class LiF {
public:
    const LiF& operator= (const LiF &l) {
        lif = l.lif;
        return *this;
    }
    const LiF& set(int _lif) {
        lif = _lif;
        return *this;
    }
private:
    int lif;
};

LiF l1, l2, l3;
l1 = l2 = l3; // 合法
(l1 = l2) = l3; // 非法,重载后的赋值运算符返回值是常量,不能再次赋值

LiF l4;
l4.set(1); // 合法
l4.set(1).set(2); // 非法,set(1)之后返回的是常量this

Guess you like

Origin www.cnblogs.com/Li-F/p/11519961.html