c++基礎(const關鍵詞, 命名空間, 引用, 內聯函數)


title: c++基礎(const關鍵詞, 命名空間, 引用, 內聯函數)
date: 2018-09-11 18:09:01
tags:


正好這學期在學c++, 打算把自己學習的都記錄一下.

這篇文章主要是c++中的一些不同于c的特性.

const關鍵詞

const通常用來表示常量,主要有以下一些用法:

符號常量

const type V = value表示V是一個常量.

在c語言中常量可以用宏定義, 如#define PI 3.14. 這種方式在編譯時把代碼中的PI全都替換為3.14, 就是說PI這個常量是沒有被保存在內存中的. 而用cosnt定義的變量會保存在內存的常量區.

修飾函數形參

用cosnt修飾的形參在函數指向過程中不能被修改.

int func(const int a) {
//    a++;//error
    return a + 5;
}

當一個函數的功能明確不能或者不需要修改參數時可以用cosnt修飾該參數.

修飾指針變量

const修飾指針變量有以下三種情況:

指向常量的指針

指向常量的指針, 也可以指向變量, 但是指針認為它指向了常量, 所以不能通過指針修改.

    cosnt int a = 10;
    int b = 11;
    const int *p_a = &a;//a是常量
    const int *p_b = &b;//ok, 指向常量的指針也能指向變量
//    *p_a = 5;//error
//    *p_b = 6;//error雖然指向變量, 但是不能通過指針修改

常指針

指針變量是個常量, 必須初始化. 不能指向常量(常量只能被指向常量的指針指向), 可以通過指針修改. 其實就相當于一個普通指針, 但是賦初值后不能修改指向的地址.

//    int *const p = &a;//error
//    不能指向常量
    int *const p = &b;
    *p = 20;//ok
//    p = &a;//error
//    不能被修改

類中的this指針就是個常指針, 只能指向當前對象.

指向常量的常指針

只能指向常量, 而且本身是個常量, 是前兩者的結合體.

//      c 指向常量的常指針 什么都不能改
    const int *const p_c = &a;

命名空間(namespace)

namespace可以用來區別不同文件里的相同名稱的函數, 變量等.

namespace first_space {
    int a = 10;

    int func(const int a);
//    嵌套namespace
    namespace second_space {
        int b = 11;
    }
}

//不連續命名空間
namespace first_space {
//    int a = 10;//error
    int b = 12;
}

//對命名空間中函數的實現
int first_space::func(const int a) {
    return a + 10;
}

要使用命名空間中的成員, 需要使用::運算符, 如first_space::a.

可以用using namespace space_name;來表示使用的命名空間, 這樣可以省略命名空間, 比如要使用c++的標準庫, 一般會using namespace std;.

引用(reference)

引用相當于給變量取個別名.

int e = 10;
int &f = e;
cout << e << endl;
f = 11;
cout << e << endl;

這里f相當于是e的一個別名, 修改兩者中的任何一個, 另一個會跟著一起改變.

按引用傳參

c++的默認傳參方式是按值傳參, 實參的值會被復制到形參中.

而按引用傳參不會復制, 而是直接引用實參, 不過會給實參取一個別名.

void add_five(int &a) {
    a += 5;
}

其實大多數編程語言都是默認都是按值調用(call by value), 比如對于java來說只有call by value, 而c++有兩種參數傳遞方式: 按值調用(call by value), 按引用調用(call by reference).

指針傳遞

c++傳遞指針作為參數, 還是call by value

void func(int *p) {
    *p = 10;//通過指針可以修改指向的值
    p = NULL;//但是調用處的指針變量不會因為p變成NULL也變成NULL
    //因為調用處把傳遞的指針的值復制一份給了p, 修改p不會改變原來指針的值
}

java call by reference?

java中的對象變量儲存的是對象的應用, 那么把對象變量作為參數傳遞是call by reference嗎? 事實上, 這還是call by value, 不過傳遞的是引用的備份, 類似于c/c++中傳遞指針.

public static void swap(Object a, Object b) {//doesn't work
    Object temp = a;
    a = b;
    b = a;
}
//call
swap(a, b);

調用swap函數處a, b的值并沒有變化, 因為函數中只是a, b引用的備份, 并非調用處a, b. 而正真的call by reference 是可以改變調用處實參的值.

void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = a;
}
//call
int a = 4, b = 5;
swap(a, b);
//a = 5, b =4

好像很多人都沒有搞清楚call by reference, 事實上call by reference只存在少數編程語言中. 雖然有時它的應用會簡化程序, 不過個人認為call by value更加符合程序設計原則(不負責任偏激的見解).

修飾函數返回值

這是個有點變態的操作, 暫時沒有搞懂有什么神奇操作

int &fn(int &b) {
    return b;
}
//main
int n = 9;
fn(n) = 11;
//此時n=11

是不是很變態, 我第一看到也一臉懵逼.

內聯函數(inline)

內聯函數, 這是一個很實用的特性. 內聯函數并不會真的被調用, 簡單來說就是把函數的語句直接復制到執行的地方執行, 但是又不是像宏無腦的替換. 對于一些經常調用的函數, 這樣可以減少函數調用的開銷.

inline int max(int a, int b) {
    return a > b ? a : b;
}

//main
int a = 10, b = 20;
int c = max(++a, --b);
//c = 19

調用max的地方語句會被這樣替換:

++a;
--b;
int c = a > b ? a : b;

對比以下宏定義的方式:

#define max(a, b) ((a) > (b) ? (a) : (b))
//main
int a = 10, b = 20;
int c = max(++a, --b);
//c = 18
//此處語句被替換為
int c = (++a) > (--b) ? (++a) : (--b);
//所以最后結果為18
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。