劍指Offer讀書筆記(持續更新中)
(1)定義一個空的型別,裡面沒有任何成員變數和成員函式,對該型別求sizeof,得到的結果是多少?
答案是1。空型別的例項中不包含任何資訊,本來求sizeof應該是0,但是當我們宣告該型別例項的時候,它必須在記憶體中佔有一定的空間,否則無法使用這些例項。至於佔用多少記憶體,由編譯器決定。Visual Studio中每個空型別的例項佔用1位元組的空間。
如果在該型別中新增一個建構函式和解構函式,再對該型別求sizeof,得到的結果又是多少?
答案還是1。呼叫建構函式和解構函式只需要知道函式的地址即可,而這些函式的地址只與型別相關,而與型別的例項無關,編譯器也不會因為這兩個函式而在例項內新增任何額外的資訊。
如果把上述的解構函式標記為虛擬函式,情況會怎樣?
C++編譯器一旦發現一個型別中有虛擬函式,就會為該型別生成虛擬函式表,並在該型別的每一個例項中新增一個指向虛擬函式表的指標,在32位的機器上,一個指標佔4位元組的空間,因此求sizeof得到4,如果是64位的機器,一個指標佔8位元組的空間,因此求sizeof得到8.
(2)看C++程式,判斷結果:
#include <iostream>
class A{
private:
int value;
public:
A(int n){
value = n;
}
A(A other){
value = other.value;
}
void Print(){
std::cout<<value<<std::endl;
}
};
int main(int argc, const char * argv[]) {
A a = 10;
A b = a;
b.Print();
return 0;
}
選擇A.編譯錯誤 B.編譯成功,執行時程式崩潰 C.編譯執行正常,輸出10
答案是A,編譯出錯。
我把程式放到IDE中,報錯行數和提示如下:
。
錯誤提示是說複製建構函式傳遞的第一個引數必須是引用型別。在上述程式碼中,複製建構函式A(A other)傳入的引數是A的一個例項。由於是傳值引數,我們把形參複製到實參會呼叫複製建構函式。因此如果允許複製建構函式傳值,就會在複製建構函式內呼叫複製建構函式,就會形成永無休止惡遞迴呼叫從而導致棧溢位。因此C++標準不允許複製建構函式傳值引數。在Visual Studio和GCC中,都會編譯出錯。要解決這個問題,就是把傳值引數修改為常量引用。程式碼如下:
A(A const &other){
value = other.value;
}
(3)題目:如下為型別CMyString的宣告,請為該型別新增賦值運算子函式。
class CMyString{
public:
CMyString(char* pData = NUll);
CMyString(const CMyString& str);
~CMyString(void);
private:
char* m_pData;
};
解決該問題應該首先注意以下幾點:
1.是否把返回值的型別宣告為該型別的引用,並在函式結束前返回例項自身的引用(即*this)。只有返回一個引用,才可以允許連續賦值。否則如果函式的返回值是void,應用該賦值物件符將不能做連續賦值。假設有三個CMyString物件,str1,str2,str3,在程式中語句str1=str2=str3將不能通過編譯。
2.是否把傳入的引數的型別宣告為常量引用。如果傳入的引數不是引用而是例項,那麼從形參到實參會呼叫一次複製建構函式。把引數宣告為引用可以避免這樣的無謂的消耗,能提高程式碼的效率。同時,我們在賦值運算子函式內不會改變傳入的例項的狀態,因此應該為傳入的引用引數加上const關鍵字。
3.是否釋放例項自身已有的記憶體。如果我們忘記在分配新記憶體之前釋放自身已有的空間,程式將出現記憶體洩露。
4.是否判斷傳入的引數和當前的例項(*this)是不是同一個例項。如果是同一個,則不進行賦值操作,直接返回。如果事先不判斷就進行賦值,那麼在釋放例項自身的記憶體的時候就會導致嚴重的問題:當*this和傳入的引數是同一個例項時,那麼一旦釋放了自身的記憶體,傳入的引數的記憶體也同時被釋放了,因此再也找不到需要賦值的內容了。
實現程式碼如下:
CMyString& CMyString::operator = (const CMyString &str){
if(this == &str){
return *this;
}
delete []m_pData;
m_pData = NULL;
m_pData = new char[strlen(str.m_pData) + 1];
strcpy(m_pData,str.m_pData);
return *this;
}
(4)C++中可以使用struct和class來定義型別,這兩種型別有什麼區別?
如果沒有標明成員函式或者成員變數的訪問許可權級別,在struct中預設是public,在class中預設是private。
github主頁:https://github.com/chenyufeng1991 。歡迎大家訪問!
相關文章
- 《Python 簡明教程》讀書筆記(持續更新)Python筆記
- 《CSS世界》閱讀筆記,持續更新CSS筆記
- 彙編筆記(持續更新中)筆記
- 日常工作筆記(持續更新中。。)筆記
- 軟考筆記 --- 持續更新筆記
- 劍指Offer系列刷題筆記彙總筆記
- iOS開發備忘筆記 (持續更新中)iOS筆記
- drupal7學習筆記—–(持續更新中…)筆記
- 【持續更新...】ligerGrid 學習筆記筆記
- 【持續更新...】ECharts學習筆記Echarts筆記
- 【持續更新...】Nginx 學習筆記Nginx筆記
- Java 學習筆記(持續更新)Java筆記
- [劍指offer] JAVA版題解(完整版)更新中。。。Java
- Web命令執行筆記(持續更新)Web筆記
- 【持續更新...】Microsoft SSIS 學習筆記ROS筆記
- 劍指offer刷題記錄
- 劍指OFFER
- 劍指Offer-連續子陣列中的最大和陣列
- ✏️ JavaScript版 | 10大專題 | 劍指offer刷題筆記 ✏️JavaScript筆記
- Mysql索引讀書筆記(待續)MySql索引筆記
- Node.js 學習筆記_20170924(持續更新…)Node.js筆記
- 【少用會忘】PHP 函式筆記(持續更新)PHP函式筆記
- 刷題記錄:劍指offer+遇到的筆試題+LeetCode筆試LeetCode
- [oracle零碎筆記]oracle零碎筆記(持續更新…)Oracle筆記
- LeetCode-劍指Offer刷題記錄LeetCode
- 劍指offer導航
- Leetcode劍指offer(八)LeetCode
- 劍指 offer21
- 劍指offer16
- 劍指 offer20
- [Android學習筆記]雜碎知識(持續更新)Android筆記
- git使用、持續更新中Git
- 劍指 Offer 42.連續子陣列的最大和陣列
- 愛玩手機的貓Linux學習筆記(持續更新)Linux筆記
- 劍指offer-JavaScript版JavaScript
- 【劍指Offer】矩形覆蓋
- 劍指Offer題解合集
- 劍指offer——跳臺階
- 六、劍指 Offer(25~29)