c++重點知識點

- const增強

在變量前加const,說明變量是常量只讀屬性。假如用指針去修改const常量會用什麼結果。上例子:ios

//a 是一個只讀的常量,按照理論應該不能被修改
    const int a = 10;//內存中爲a分配地址,賦值
    printf("sssss:&a:%d", &a);
    int *p = NULL;
    int *p2 = NULL;
    //當你對a取地址的時候,有一個內存空間(&a a的內存空間)
    p = (int *)&a;//此時取常量地址,同時將a值存在符號表中
    printf("&a:%d p的值:%d", &a, p);
    *p = 11;//修改內存中值
    printf("修改以後a:%d \n", a);//經過常量a(修飾符號表)而不是以前內存地址了。讀取符號表中的值。
    printf("*p:%d \n", *p);//讀取內存中值,此時已經修改
    printf("*p2:%d \n", *p2);//再次讀取內存中,發現是11.
    system("pause");
View Code

 

這裏寫圖片描述
在c++中const變量是隻讀的,當聲明這個變量爲常量的時候,這個變量不能修改。加入用指針獲取地址,修改時,會數值分配到符號表,指針能夠修改數值,可是變量a的值沒有變化。
const和define區別
(1) 編譯器處理方式不一樣
  define宏是在預處理階段展開。
  const常量是編譯運行階段使用。
(2) 類型和安全檢查不一樣
  define宏沒有類型,不作任何類型檢查,僅僅是展開。
  const常量有具體的類型,在編譯階段會執行類型檢查。
(3) 存儲方式不一樣
  define宏僅僅是展開,有多少地方使用,就展開多少次,不會分配內存。
  const常量會在內存中分配(能夠是堆中也能夠是棧中)。c++

(4)const 能夠節省空間,避免沒必要要的內存分配。 例如: 編程

#define PI 3.14159 //常量宏 
const doulbe Pi=3.14159; //此時並未將Pi放入ROM中 …… 
double i=Pi; //此時爲Pi分配內存,之後再也不分配! 
double I=PI; //編譯期間進行宏替換,分配內存 
double j=Pi; //沒有內存分配 
double J=PI; //再進行宏替換,又一次分配內存! 
View Code

 


const定義常量從彙編的角度來看,只是給出了對應的內存地址,而不是象#define同樣給出的是當即數,因此,const定義的常量在程序運行過程當中只有一份拷貝,而 #define定義的常量在內存中有若干個拷貝。
(5) 提升了效率。 編譯器一般不爲普通const常量分配存儲空間,而是將它們保存在符號表中,這使得它成爲一個編譯期間的常量,沒有了存儲與讀內存的操做,使得它的效率也很高。安全

const 與 #define的比較
C++ 語言能夠用const來定義常量,也能夠用 #define來定義常量。可是前者比後者有更多的優勢:
(1) const常量有數據類型,而宏常量沒有數據類型。編譯器能夠對前者進行類型安全檢查。而對後者只進行字符替換,沒有類型安全檢查,而且在字符替換可能會產生意料不到的錯誤(邊際效應)。
(2) 有些集成化的調試工具能夠對const常量進行調試,可是不能對宏常量進行調試。markdown

l 【規則5-2-1】在C++ 程序中只使用const常量而不使用宏常量,即const常量徹底取代宏常量。ide

- 構造函數

  • 構造函數定義函數

    1. 在c++中有三種構造函數,構造函數是c++中用於初始化對象初始狀態的特殊函數。
    2. 構造函數在對象建立是自動調用,隱身調用。
    3. 構造函數和普通成員構造函數遵循重載規則
    4. 拷貝構造函數是對象正確初始化的重要保證。
    5. 析構函數在對象週期結束時調用。
  • 拷貝構造函數工具

    1. 拷貝構造函數也是構造函數,用來構造對象。
    2. 拷貝構造函數和=是兩個不一樣概念
    3. 當咱們沒有編寫拷貝構造函數的時候便一塊兒你會默認提供copy構造函數,執行的是淺拷貝。(test t= t2;)
    4. 函數返回 類類型是,經過複製構造函數創建臨時對象。
class Location
{
public:
    Location( int xx = 0 , int yy = 0 )
    {
        X = xx ;  Y = yy ;  cout << "Constructor Object.\n" ;
    }
    Location( const Location & p )      //複製構造函數
    {
        X = p.X ;  Y = p.Y ;   cout << "Copy_constructor called." << endl ;  }
    ~Location() { cout << X << "," << Y << " Object destroyed." << endl ; }
    int  GetX () { return X ; }     int GetY () { return Y ; }
private :   int  X , Y ;
} ;

void f ( Location  p )
{
    cout << "Funtion:" << p.GetX() << "," << p.GetY() << endl ;
}
// void playobjmain()
// {
//  Location A ( 1, 2 ) ;
//  f ( A ) ;
// }
Location g()
{
    Location A(1, 2);//構造函數調用第二次
    return A;//一、(由於返回對象類型)編譯器會自動建立一個臨時對象調用構造函數,調用拷貝構造函數。
    //二、由於須要返回,生命週期結束,對象A進行釋放,調用析構函數
}
void main101()
{
    Location B;//構造函數調用一次
    //開始進入被調用函數
    B = g();//在賦值結束後,建立的臨時對象須要銷燬,調用了一次析構函數

}

int main()
{
    main101();//被調用函數結束了,第三次調用析構函數,析構對象B
    system("pause");
    return 0;
}
View Code

 

內存角度分析類

在c++中是面向對象編程,將變量(屬性)和函數(方法)集中定義在一塊兒,用於抽象描述現實世界的類。從計算機角度,程序依然由數據和代碼段構成。那麼從編譯器角度如何完成面向對象理論到計算機程序的轉化?也就是編譯器如何管理類、對象、類和對象之間的關係。看一下代碼:佈局

#include "iostream"
using namespace std;
class C1
{
public:
    int i; //4 
    int j; //4
    int k; //4
protected:
private:
}; //變量很容易判斷分配在內存中。

class C2
{
public:
    int i; //4
    int j; //4
    int k; //4  
    static int m; //4
public:
    int getK() const { return k; } //4
    void setK(int val) { k = val; } //4

protected:
private:
}; //從上面分析中函數會提供函數函數指針,理論上是每一個函數佔用四個字節。若是這樣的話,加入建立100多個對象,那內存不是佔用不少,這樣很不合理。同事變量是怎麼處理的呢?實際內存大小是12,靜態成員在全局區,屬性整個類,不是對象。

struct S1
{
    int i;
    int j;
    int k;
}; //12

struct S2
{
    int i;
    int j;
    int k;
    static int m;
}; //16

int main()
{
    printf("c1:%d \n", sizeof(C1));
    printf("c2:%d \n", sizeof(C2));
    printf("s1:%d \n", sizeof(S1));
    printf("s2:%d \n", sizeof(S2));

    system("pause");
}
View Code

 

那麼用內存四區概念解析c++中屬性和方法this

  • c++類對象中成員變量和成員函數時分開存儲的。
    • 成員變量:
      • 普通成員變量:存儲在對象中,與struct變量有相同的內存佈局和字節對齊方式
      • 靜態成員變量:存儲與全局數據區。
    • 成員函數:存儲於代碼段中。 不少對象公用一塊代碼段,代碼是怎麼如何區分具體對象?其實在c++中類普通成員函數都隱式包含一個指向當前對象的this指針。 靜態成員函數是屬於整個類的額,因此沒有隱式的this指針。
相關文章
相關標籤/搜索