1. 程式人生 > >學習筆記1 從C到C++

學習筆記1 從C到C++

本篇文章是學習c++面向物件程式設計前遇到的一些需要注意的知識點,因此做個記錄>=<。。。

引用返回&傳值返回

  • 引用返回 &
    C++中,在預設情況下,當函式返回一個值時:
    return expression;
    expression被求值,並將該值拷貝到臨時儲存空間,以便函式呼叫者訪問。這種返回方式稱為傳值返回
    例如:當呼叫以下函式

    int val1()
    {
    	//...
    	return i;
    }	
    

時,i的值將拷貝到臨時儲存空間,呼叫者獲得的是i的一個副本,也就是說,如果呼叫函式val1:j = val1();,則i的值將拷貝到臨時儲存空間,然後再拷貝到j。
引用返回

,返回值不拷貝到臨時儲存空間,甚至連return語句所用的那個儲存單元對呼叫者而言都是可訪問的。
例如:當呼叫以下函式

```c
int& val2()
{
	//...
	return i;
}
```

的返回型別為int&.當return語句執行後,呼叫者可以直接訪問i。
例如:以如下方式呼叫函式val2j = val2();,則i的值直接拷貝到j中,與傳值返回不同的是,僅產生一個副本。

  • 警告
    例如函式:
int& f()
{
	int i;
	//...
	//**** ERROR:i已經不存在了
	return i;
}

包含了一個錯誤。當f返回i時,i已經不存在了(因為i是區域性變數)。

行內函數

關鍵字:inline
行內函數類似於巨集拓展。當處理器拓展一個巨集時,它將用巨集定義替換每個巨集。當巨集替換或函式拓展完成後,再執行程式,這樣避免了函式呼叫的開銷,程式可以更有效地執行。使用巨集行內函數的缺點是,如果函式很大,或很多地方都呼叫了這個函式,程式的可執行碼將變得很大。
行內函數的拓展是通過編譯器完成的。當前處理器拓展一個巨集時,它只是進行簡單的文字替換,而不考慮程式碼的語義。而編譯器拓展行內函數時,需要考慮語義。
inline函式從宣告開始到檔案結束都是可見的。
如下程式:

#include<iostream>
using namespace std;
inline void swap(int& a,int& b) { int t; t=a; a=b; b=t; } int main() { int i=7,j=-3; swap(i,j); cout<<i<<" "<<j<<endl; return 0; }

編譯器接受以內聯方式拓展swap函式的請求,對程式碼swap(i,j);來說不產生函式呼叫操作,因為swap是行內函數,編譯器用swap的實現程式碼來替代這一行程式碼。

new和delete操作符

new、new[]、delete和delete[]操作符用於動態分配和釋放儲存空間。操作符new分配一個空間;new[]分配一個數組;delete釋放由new分配的單一空間;*delete[]釋放由new[]*分配的陣列。這些操作符與C語言中的函式malloc、calloc和free。不同的是,**new、new[]、delete和delete[]**是內建的操作符,而不是庫函式。而且,new和delete還是關鍵字。

  • 分配一個int儲存空間,如果new分配成功,則表示式:new int
    例如:
    int* intptr = new int;

  • 分配一個int動態陣列。
    例如:int_ptr = new int[50];

  • delete釋放由new分配的儲存空間,例如:delete int_ptr;

  • **delete[]釋放由new[]**分配的儲存空間,例如:delete[] int_ptr;

混用c和c++的輸入/輸出功能

可使用函式ios::sync_with_stdio();來消除這種隱患。
例如程式碼:

#include<cstdio>
#include<iostream>
using namespace std;

int main()
{
	int a=2,b=5;
	ios::sync_with_stdio();
	printf("%d ",a);
	cout<<b<<'\n';
	return 0;
}