在變量前加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");
在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; //再進行宏替換,又一次分配內存!
const定義常量從彙編的角度來看,只是給出了對應的內存地址,而不是象#define同樣給出的是當即數,因此,const定義的常量在程序運行過程當中只有一份拷貝,而 #define定義的常量在內存中有若干個拷貝。
(5) 提升了效率。 編譯器一般不爲普通const常量分配存儲空間,而是將它們保存在符號表中,這使得它成爲一個編譯期間的常量,沒有了存儲與讀內存的操做,使得它的效率也很高。安全
const 與 #define的比較
C++ 語言能夠用const來定義常量,也能夠用 #define來定義常量。可是前者比後者有更多的優勢:
(1) const常量有數據類型,而宏常量沒有數據類型。編譯器能夠對前者進行類型安全檢查。而對後者只進行字符替換,沒有類型安全檢查,而且在字符替換可能會產生意料不到的錯誤(邊際效應)。
(2) 有些集成化的調試工具能夠對const常量進行調試,可是不能對宏常量進行調試。markdown
l 【規則5-2-1】在C++ 程序中只使用const常量而不使用宏常量,即const常量徹底取代宏常量。ide
構造函數定義函數
拷貝構造函數工具
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; }
在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"); }
那麼用內存四區概念解析c++中屬性和方法this