變量(定義 初始化)、臨時變量

聲明與定義
變量的聲明(如:extern int a;聲明外部變量)告訴編譯器變量名字與類型;
變量的定義:爲變量分配存儲空間,此時也可以給定初始值;
函數的聲明:告訴編譯器有這麼一個函數;
函數的定義:實現函數,簡言之就是帶有{ };
 
與結構體一樣,類只是一種複雜數據類型的聲明,不佔用內存空間。
而對象是類這種數據類型的一個變量,或者說是通過類這種數據類型定義了一個變量(對象),是佔用內存空間的。
calss Point{
};
 
Point t1; // 將調用構造函數
Point *t1;// 不調用構造函數
 
聲明一個指針 int *p;表示*p的類型爲int,p是指向int類型的指針;(即p爲int* ; *p爲int)
定義 int *p 時,p位於棧區,佔有內存空間是系統分配,系統將給定一個隨機地址(不確定地址)給p;
void main_5()
{
    int *p;     
    printf("0x%x \n", p);
    *p = 5;
    printf("%d \n", *p); // 若無上句的賦值(給確切的內存地址),將非法訪問內存,程序奔潰
}
 
 
 
 
 
二、臨時變量的產生
臨時變量只在調用期間有效,有三種方式產生:函數返回時、類型轉換時、形式參數爲const時
1、函數返回時,以值或是指針形式返回時;
int sum(int a,int b)
{
    return a + b;//編譯器會將結果a+b的值拷貝給臨時變量,最終返回的是臨時變量;
}
2、在進行 強制類型轉換時;
double a = 10.5;
cout << (int)a ;// 在強轉時,一定生成臨時變量,原始數據本身並沒有改變。
cout << a;
3、函數形參爲const來保護原始數據;
 
 
 
 
三、初始化
C++的初始化方式:默認初始化、值初始化、直接初始化、拷貝初始化、列表初始化;
 
默認初始化
1、未初始化的 全局內置類型(int、double)變量;
2、類 類型,都會執行默認構造函數;如string、vector<int>;
 
值初始化
值初始化是值使用了初始化器(即使用了圓括號或花括號)但卻沒有提供初始值的情況;
vector<int> v1(10);//10個元素,每個元素的初始化爲0
vector<string> v2(10);//10個元素,每個元素都爲空
vector<int> v4(10, 1);//v3有10個元素,每個的值都是1
vector<int> v3{10};//v2有1個元素,該元素的值是10
vector<int> v5{10, 1};//v4有2個元素,值分別是10和1
int *p = new int();
 
 
直接初始化
直接初始化是指採用小括號()而不使用等號=的方式進行變量初始化;
string str1(10,'9');//直接初始化
string str2(str1);//直接初始化
 
 
拷貝初始化
使用等號(賦值號=)進行初始化,編譯器把等號右側的初始值拷貝到新創建的對象中去,拷貝初始化通常使用拷貝構造函數來完成。拷貝初始化看起來像是給變量賦值,實際上是執行了初始化操作,與先定義再賦值本質不同。
int a = 0;
int a = {0};
string str1 = "hello";
string s=string("123456");
 
初始化列表
爲C++11採用的初始化方式,使用{}進行初始化操作,下列三種情況需要用到初始化成員列表:
1、類的數據成員中含有不帶默認構造函數的對象(包括在繼承時顯示調用父類的構造函數對父類成員初始化);
2、類的數據成員中含有const修飾類型的或引用類型;(因爲這兩種對象要在聲明後馬上初始化);
3、子類初始化父類的私有成員
vector<int> v4{1, -2, 3, 10, -4}; // 等價於 v4 = {1, 2, 3, ....} 
int b[5]{10,20,30,40,50}; // a[] = {10,20,30,40,50};
 
class People{
    public:
        People(string n="", int a = -1) : age(a)name(n){} // 列表初始化
    private:
        string name;
        int age;
};
 
注意:初始化列表中變量的執行順序是由成員變量的聲明順序來決定的,上述並不先執行age(a),而是先執行name(n);
 
【舉例1】
class A {
    ...
    private:
       int &a;
};
class B : public A {
    ...
    private:
         int a;
    public:
         const int b; // 數據成員中含有const修飾類型的或引用類型,必須通過初始化列表來初始化;
         A c; // 數據成員中含有不帶默認構造函數的對象,必須通過初始化列表來初始化;
         static const char* d;
         A* e;
};
 
 
 
類對象的顯式初始化
Data data1(2019,9,22);//顯式初始化,直接調用構造函數
Data* b = new Data(2019,9,22);//顯式初始化,直接調用構造函數,使用delete時析構
Data p = Data(2019,9,22);//顯式初始化,直接調用構造函數,沒有臨時對象,作用域結束時析構
Data B(data1);//顯式初始化,調用拷貝構造函數,作用域結束時析構
 
 
類對象的隱式初始化
Data b = a;//用一個對象隱式初始化另一對象,調用拷貝構造函數,作用域結束時析構
 
 
 
 
 
C++11 initialize_list類模板(初始化類模板 #include<initalize_list>
 
#include <iostream>
#include <vector>
class MyNumber
{
public:
    MyNumber(const std::initializer_list<int> &v) {// C++11允許構造函數和其他函數把初始化列表當做參數。
        for (auto itm : v) {
            mVec.push_back(itm);
        }
    }
    void print() {
    for (auto itm : mVec) {
        std::cout << itm << " ";
    }
  }
private:
    std::vector<int> mVec;
};
 
int main()
{
    MyNumber m{ 1, 2, 3, 4 }; // calls initializer_list
    m.print();  // 1 2 3 4
    
    MyNumber m2{ 10, 20, 30, 40 }; // calls initializer_list
    m2.print();  // 10 20 30 40
 
    return 0;
}
 
 
 
 
 
 
 
 
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章