C++基礎知識,減少臨時變量,提升效率,類外運算符

i++,++i的討論引題
  • 臨時對象都是右值
//臨時對象
//i++,右值,會產生一個臨時對象,
//如何保存這個臨時對象
int i = 0;
int&& saveI = i++;//這樣寫的話,這個臨時變量就會一直保存到程序結束,saveI和i之間沒有什麼關係
  • 爲什麼減少臨時變量能提升系統效率呢?
    要知道臨時對象是存貯在中的,如果寫代碼的時候能減少臨時變量的產生,將會提升系統的效率

一:產生臨時對象的情況和解決方案

1、以傳值的方式給函數傳遞參數,這個用得太多了,所以就不舉例說明了

2、類型轉換生成的臨時對象 / 隱式類型轉換以保證函數調用成功

2.1 類型轉換生成的臨時對象
class classA
{
public:
	int val1;
	int val2;

public:
	classA(int a = 1, int b = 2);
	classA(const classA& obj);
	virtual ~classA();
	classA& operator=(const classA& obj);
};


classA::classA(int a, int b) :val1(a), val2(b)
{
	cout << "調用了構造函數" << endl;
	cout << "val1 = " << val1 << endl;
	cout << "val2 = " << val2 << endl;
}

classA::classA(const classA& obj)
{
	cout << "調用了拷貝函數" << endl;
	val1 = obj.val1;
	val2 = obj.val2;
}

classA::~classA()
{
	cout << "調用了析構函數" << endl;
}

classA& classA::operator=(const classA& obj)
{
	cout << "調用了賦值運算符" << endl;
	val1 = obj.val1;
	val2 = obj.val2;
	return *this;
}

int main()
{
	classA myClassA;
	myClassA = 1000;//這一步用的是賦值運算符
}

運行結果:
在這裏插入圖片描述
可以看出,就這一個“=”號就做了三件事情

  • 1、執行了構造函數,創建了一個臨時變量
  • 2、執行了賦值運算符,將值傳遞給對象
  • 3、執行了析構函數

這樣系統白白多執行了三個步驟
我們如何改進呢?
最好初始化的時候就賦值,這樣就不會生成臨時變量

classA myClassA = 1000;

執行效果如下
在這裏插入圖片描述

2.2 隱式類型轉換以保證函數調用成功

//可以看到,傳遞進來的參數是char數組,而接收卻用的是const string& 
//這裏系統就會直接進行隱式類型轉換
//那麼可不可以用string& 來接收呢?
//那肯定是不行的,正面理解比較困難,我們反着理解
//如果你用了string& sourceStr 來接收,系統會認爲你有權限去改變sourceStr
//但是這個string是系統給你構造的臨時變量,不會造成原先char數組的改變,系統爲了防止你無意中犯下這個錯誤
//編譯的時候就會告訴你出錯
//系統會爲const string& sourceStr構造臨時變量
//但是不會爲string& sourceStr構造臨時變量
int testMethod1(const string& sourceStr, char x)
{
	const char* p = sourceStr.c_str();
	int count = 0;
	//todo
	return count;
}
int main()
{
	char myCharArray[100] = "I Love You";
	int result = testMethod1(myCharArray, 'o');
	cout << result << endl;
}

3、函數返回對象的時候

classA testMethod2(classA& obj)
{
	classA myNewClassA;
	myNewClassA.val1 = obj.val1;
	myNewClassA.val2 = obj.val2;
	return myNewClassA;
}
int main()
{
	classA myClassB;
	testMethod2(myClassB);
}

這裏return myNewClassA的時候,也會創造一個臨時變量
執行效果如下:可以看出,我們只顯式聲明瞭兩個對象,可是卻調用了三次析構函數,一次拷貝構造函數,可以得出結論:
return myNewClassA的時候,會創造一個臨時變量
在這裏插入圖片描述
那麼如何改進呢?

classA testMethod2(classA& obj)
{
	return classA(obj.val1, obj.val2);//這樣就不會構造臨時對象了
}
int main()
{
	classA myClassB;
	//這裏直接接收返回的對象,會保存函數內部創建的對象
	classA myNewClassB = testMethod2(myClassB);
}

執行效果如下:
在這裏插入圖片描述

二:類外運算符重載

class testclass
{
public:
	testclass(int a = 0, int b = 0) :a(a), b(b) {};
public:
	int a;
	int b;
};

//這是經過優化過臨時變量的類外運算符重載
testclass operator+(testclass& class1, testclass& class2)
{
	return testclass(class1.a + class2.a, class1.b + class2.b);
}
int main()
{
	testclass class1(1, 2);
	testclass class2(1, 2);
	testclass class3 = class1 + class2;
	cout << class3.a << endl;
	cout << class3.b << endl;
	
	return 0
}

運行結果如下:
在這裏插入圖片描述

發佈了157 篇原創文章 · 獲贊 167 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章