福州搜索優(yōu)化實(shí)力江蘇seo哪家好
目錄
1.構(gòu)造函數(shù)初始化列表
1.1 構(gòu)造函數(shù)初始化列表與函數(shù)體內(nèi)初始化區(qū)別
1.2 必須在初始化列表初始化的成員
2 引用&引用與指針的區(qū)別
2.1 引用初始化以后不能被改變,指針可以改變所指的對象
?2.2 引用和指針的區(qū)別
3 構(gòu)造函數(shù)與析構(gòu)函數(shù)系列題
3.1構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用次數(shù)
4 類的運(yùn)算符重載
5 類的靜態(tài)數(shù)據(jù)成員
5.1 malloc/new/new[]
5.2 new的實(shí)現(xiàn)步驟與細(xì)節(jié)
6 this指針相關(guān)題目?
6.1 this可以為空嗎?
6.2 this指針存放在哪里?
6.3?delete this
7 其他于類相關(guān)的題目
7.1 空類的大小
7.2 對const變量的修改
??volatile
?7.3 賦值運(yùn)算符重載
1.構(gòu)造函數(shù)初始化列表
有一個(gè)類A,其數(shù)據(jù)成員如下: 則構(gòu)造函數(shù)中,成員變量一定要通過初始化列表來初始化的是:______。
class A { ... private:int a; public:const int b;float* &c;static const char* d;static double* e; };
A. a b c
B. b c
C. b c d e
D. b c d
E. b
F. c
答案:B
知識點(diǎn):
1.1 構(gòu)造函數(shù)初始化列表與函數(shù)體內(nèi)初始化區(qū)別
一個(gè)類,其包含一個(gè)類類型成員,對于它的構(gòu)造函數(shù),如果在函數(shù)體內(nèi)初始化,會(huì)先調(diào)用其類類型成員的默認(rèn)構(gòu)造函數(shù),在調(diào)用賦值運(yùn)算符,而在構(gòu)造函數(shù)初始化時(shí)會(huì)直接調(diào)用它的拷貝構(gòu)造函數(shù)進(jìn)行初始化
函數(shù)體類初始化:
#include <iostream>class B {
public:B() { std::cout << "B defualt construct" << '\n'; }B(int t) : _t(t) { std::cout << "B construct" << '\n'; }B(const B& b) : _t(b._t) { std::cout << "B copy construct" << '\n'; }B& operator=(const B& b) {_t = b._t;std::cout << "B assign operator"<< '\n';return *this;}
private:int _t = 0;
};
class A {
public:A() { std::cout << "A defualt construct" << '\n'; }A(const B& b){ puts("---------------------");_b = b;std::cout << "A construct" << '\n'; }A(const A& a) : _b(a._b) { std::cout << "A copy construct" << '\n'; }A& operator=(const A& a) {_b = a._b;std::cout << "A assign operator" << '\n';return *this;}
private:B _b;
};
int main() {B b(1);A a(b);
}
初始化列表初始化:
#include <iostream>class B {
public:B() { std::cout << "B defualt construct" << '\n'; }B(int t) : _t(t) { std::cout << "B construct" << '\n'; }B(const B& b) : _t(b._t) { std::cout << "B copy construct" << '\n'; }B& operator=(const B& b) {_t = b._t;std::cout << "B assign operator"<< '\n';return *this;}
private:int _t = 0;
};
class A {
public:A() { std::cout << "A defualt construct" << '\n'; }A(const B& b) : _b(b) { puts("---------------------");std::cout << "A construct" << '\n';}/*A(const B& b){ puts("---------------------");_b = b;std::cout << "A construct" << '\n'; }*/A(const A& a) : _b(a._b) { std::cout << "A copy construct" << '\n'; }A& operator=(const A& a) {_b = a._b;std::cout << "A assign operator" << '\n';return *this;}
private:B _b;
};
int main() {B b(1);A a(b);
}
1.2 必須在初始化列表初始化的成員
? const修飾的成員變量
? 引用類型成員
? 類類型成員,且該類沒有默認(rèn)構(gòu)造函數(shù)(由1.1內(nèi)容可得)
2 引用&引用與指針的區(qū)別
2.1 引用初始化以后不能被改變,指針可以改變所指的對象
int main() {int a = 10;int& ref = a; int b = 20; ref = b;std::cout << "a:" << a << " ref:" << ref << " b:" << b; //output:a:20 ref:20 b:20
}
?2.2 引用和指針的區(qū)別
引用和指針,下面說法不正確的是()
A. 引用和指針在聲明后都有自己的內(nèi)存空間
B. 引用必須在聲明時(shí)初始化,而指針不用
C. 引用聲明后,引用的對象不可改變,對象的值可以改變,非const指針可以隨時(shí)改變指向的對象以及對象的值
D. 空值NULL不能引用,而指針可以指向NULL
答案:A
#include <iostream>int main() {int a = 10;int& ref = a;std::cout << "a:" << &a << '\n' << "ref:" << &ref << '\n';//a:00FCF8D4 ref:00FCF8D4int b = 10;int* ptr = &b;std::cout << "b:" << &b << '\n' << "ptr:" << &ptr << '\n';//b : 00FCF8BC ptr: 00FCF8B0return 0;
}
?從定義內(nèi)存上看,引用和被引用變量公用同一塊空間
3 構(gòu)造函數(shù)與析構(gòu)函數(shù)系列題
3.1構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用次數(shù)
1)
C++語言中,類ClassA的構(gòu)造函數(shù)和析構(gòu)函數(shù)的執(zhí)行次數(shù)分別為()
ClassA *pclassa=new ClassA[5]; delete pclassa;
A. 5,1
B. 1,1
C. 5,5(錯(cuò)誤)
D. 1,5
答案:A?
2)
#include <iostream>
#include <string>
using namespace std;
class Test {
public:Test(){ std::cout << this << "B defualt construct" << '\n'; }~Test() { std::cout << this << "B destory" << '\n'; }
};
int main() {Test t1;puts("------------");Test* t2;puts("------------");Test t3[3];puts("------------");Test* t4[3]; //t4是存放三個(gè)類型Test*的對象的數(shù)組puts("------------");Test(*t5)[3]; //t5是數(shù)組指針,指向一個(gè)存放三個(gè)類型為Test的對象的數(shù)組puts("------------");
}
?打印結(jié)果:
4 類的運(yùn)算符重載
在重載一個(gè)運(yùn)算符為成員函數(shù)時(shí),其參數(shù)表中沒有任何參數(shù),這說明該運(yùn)算符是 ( )。
A. 無操作數(shù)的運(yùn)算符
B. 二元運(yùn)算符
C. 前綴一元運(yùn)算符
D. 后綴一元運(yùn)算符(錯(cuò)誤)
答案:C
例如:
前置++:T& operator++() {}?
后置++:T?operator++(int) {}
5 類的靜態(tài)數(shù)據(jù)成員
下面有關(guān)c++靜態(tài)數(shù)據(jù)成員,說法正確的是()
A. 不能在類內(nèi)初始化(錯(cuò)誤)
B. 不能被類的對象調(diào)用
C. 不能受private修飾符的作用
D. 可以直接用類名調(diào)用 ?
答案:D :?
知識點(diǎn):const修飾的靜態(tài)成員可以在類內(nèi)初始化,所以A錯(cuò)誤
5.1 malloc/new/new[]
malloc/calloc/realloc <----> free????????new <----> delete????????new [] <----> delete[]三者一定要匹配使用,否則會(huì)產(chǎn)生內(nèi)存泄漏或者程序崩潰
5.2 new的實(shí)現(xiàn)步驟與細(xì)節(jié)
1) 對于 T*p = new T;
-第一步: 調(diào)用operator new(size_t size)申請空間(內(nèi)部調(diào)用malloc循環(huán)申請)
-第二步: 調(diào)用構(gòu)造函數(shù)完成對申請空間的初始化
? ? ?對于 delete p;
-第一步:調(diào)用析構(gòu)函數(shù)釋放p指向的對象中的資源
-第二步:調(diào)用operator delete釋放p所指向的空間(內(nèi)部調(diào)用free)
2)對于 T*p = new T[N];
-第一步: 調(diào)用operator new[](size_t size)申請空間(內(nèi)部調(diào)用operator new(size_t size))
-第二步: 調(diào)用N次T的構(gòu)造函數(shù)完成對申請空間的初始化
? ? ?對于 delete p;
-第一步:調(diào)用N次T的析構(gòu)函數(shù)釋放p指向的N個(gè)對象中的資源
-第二步:調(diào)用operator delete[]釋放p所指向的空間(內(nèi)部調(diào)用operator delete)
6 this指針相關(guān)題目?
6.1 this可以為空嗎?
6.2 this指針存放在哪里?
6.3?delete this 以及 delete細(xì)節(jié)解析
如果有一個(gè)類是 myClass , 關(guān)于下面代碼正確描述的是:
myClass::~myClass(){delete this;this = NULL; }
A. 正確,我們避免了內(nèi)存泄漏
B. 它會(huì)導(dǎo)致棧溢出
C. 無法編譯通過? ? ? ? ? ? ? ? ? ? ? ? ? ??
D. 這是不正確的,它沒有釋放任何成員變量。(錯(cuò)誤)?
答案:C
對于上述代碼,首先它是不能被編譯通過的,因?yàn)閠his指針本身被const修飾(對于上述例子而言this指針的類型為myClass *const), this指針本身無法被修改
如果刪去`this = NULL`這一段代碼,程序還是有錯(cuò),我們通過下面幾個(gè)例子說明??
首先我們需要了解:調(diào)用delete函數(shù)之后會(huì)依次執(zhí)行下面兩個(gè)步驟?
① 對目標(biāo)調(diào)用的析構(gòu)函數(shù)
② 調(diào)用operator delete釋放內(nèi)存
通過下面幾種了解:
1)
#include <iostream>
using namespace std;class Test {
public:Test() {puts("Test()");x = 0;ptr = new int(0);}~Test() {puts("~Test() before");delete this;//this = nullptr; //編譯錯(cuò)誤 C2106“ = ”: 左操作數(shù)必須為左puts("~Test() after");}
private:int x;int* ptr;
};int main() {Test t;
}
?上面這段代碼執(zhí)行會(huì)不斷打印~Test() before,直至程序棧溢出
解釋了調(diào)用operator delete之后的執(zhí)行步驟,上述代碼會(huì)this指針指向?qū)ο蟮奈鰳?gòu)函數(shù),而析構(gòu)函數(shù)中又有delete函數(shù),導(dǎo)致死循環(huán),如下圖??
2)
#include <iostream>
using namespace std;class Test2 {
public:Test2() {ptr = new int(0);}~Test2() {puts("~Test2");delete ptr;ptr = nullptr;}void deletefunc() {delete this; //先析構(gòu),再delete this指向的堆空間(當(dāng)this指向的是棧上的空間時(shí),程序崩潰)}
private:int* ptr;int x = 0;
};
int main() {Test2* tptr = new Test2();tptr->deletefunc();
}
通過上述代碼和動(dòng)畫演示鞏固delete的兩個(gè)步驟;
如過將對象創(chuàng)建再棧中,上述程序又會(huì)出現(xiàn)bug:編譯階段不會(huì)報(bào)錯(cuò),但是再運(yùn)行到delete this的時(shí)候程序崩潰了,原因是對棧上的空間進(jìn)行了釋放
Test2 obj = Test2();obj.deletefunc();
3)
#include <iostream>
using namespace std;void operator delete(void* ptr) { puts("operator delete");
}
class Test2 {
public:Test2() {ptr = new int(0);}~Test2() {puts("~Test2");delete ptr;ptr = nullptr;}void deletefunc() {delete this; }
private:int* ptr;int x = 0;
};
int main() {Test2* ptr = new Test2();ptr->deletefunc();
}
調(diào)試上述代碼
?
7 其他于類相關(guān)的題目
7.1 空類的大小
在Windows 32位操作系統(tǒng)中,假設(shè)字節(jié)對齊為4,對于一個(gè)空的類A,sizeof(A)的值為()? A. 0
B. 1
C. 2
D. 4(錯(cuò)誤)
答案:B
類大小的計(jì)算方式:與結(jié)構(gòu)體大小的計(jì)算方式類似,將類中非靜態(tài)成員的大小按內(nèi)存對齊規(guī)則計(jì)算,并且不用計(jì)算成員函數(shù);
特別的,空類的大小在主流的編譯器中設(shè)置成了1
7.2 對const變量的修改
以下程序輸出是____。
#include <iostream> using namespace std; int main(void) {const int a = 10;int * p = (int *)(&a);*p = 20;cout<<"a = "<<a<<", *p = "<<*p<<endl;return 0; }
A. 編譯階段報(bào)錯(cuò)運(yùn)行階段報(bào)錯(cuò)
B. a = 10, *p = 10
C. a = 20, *p = 20(錯(cuò)誤)
D. a = 10, *p = 20
E. a = 20, *p = 10
?答案:D
知識點(diǎn):
1)編譯器在編譯階段會(huì)對const修飾的變量進(jìn)行優(yōu)化,將其替換成變量的值
由圖中的匯編代碼可以看到,打印變量a時(shí),他被直接替換成了10這個(gè)常量
??volatile
C/C++ 中的 volatile 關(guān)鍵字和 const 對應(yīng),用來修飾變量,volatile 關(guān)鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器未知的因素更改,比如:操作系統(tǒng)、硬件或者其它線程等。遇到這個(gè)關(guān)鍵字聲明的變量,編譯器對訪問該變量的代碼就不再進(jìn)行優(yōu)化,從而可以提供對特殊地址的穩(wěn)定訪問。
#include <iostream>
using namespace std;
int main(void)
{const int volatile a = 10;int* p = (int*)(&a);*p = 20;cout << "a = " << a << ", *p = " << *p << endl;return 0;
}
當(dāng)用volatile修飾a之后打印結(jié)果為:
?7.3 賦值運(yùn)算符重載
下列關(guān)于賦值運(yùn)算符“=”重載的敘述中,正確的是
A. 賦值運(yùn)算符只能作為類的成員函數(shù)重載
B. 默認(rèn)的賦值運(yùn)算符實(shí)現(xiàn)了“深層復(fù)制”功能
C. 重載的賦值運(yùn)算符函數(shù)有兩個(gè)本類對象作為形參(錯(cuò)誤)
D. 如果己經(jīng)定義了復(fù)制拷貝構(gòu)造函數(shù),就不能重載賦值運(yùn)算符
答案:A