今天看到公司的代碼內有大量的explicit關(guān)鍵字,但是老版的MSDN內例子并不完善,實(shí)在是不明白,最終從網(wǎng)上一篇文章內找到了答案:原來(lái)explicit是為了防止隱式使用拷貝構造函數的.以下附上從新版MSDN中找到的例子和網(wǎng)上那篇文章:
This keyword is a declaration specifier that can only be applied to in-class constructor declarations. An explicit constructor cannot take part in implicit conversions. It can only be used to explicitly construct an object.
Pointer
不看書(shū)不知道自己的C++有多差T_T,看到 explicit 時(shí)遇到一個(gè)問(wèn)題。請看下面一段程序:
class A{
public:
A(int i) : m_i(i){}
int m_i;
};
int main(){
A a = 0;
a = 10; // 這里是什么操作?
}
這個(gè)操作產(chǎn)生了一個(gè)臨時(shí)對象。
我懷疑是默認賦值運算符 “A &operator = (int i){}”,于是重載了一下該運算符,結果確實(shí)運行到重載的運算符函數里了,那么臨時(shí)對象又是如何產(chǎn)生的呢?
難道默認的賦值運算符是這樣操作的?
A &operator = (int i){
A a(i);
return a;
}
這讓我想起了類(lèi)似的函數操作:
void fn(A a){
// ...
}
這里可以直接寫(xiě)fn(10);也是產(chǎn)生了一個(gè)臨時(shí)對象。
難道真的是這樣嗎?忘解惑。
alexeyomux
老兄你用的是哪個(gè)編譯器?在我印象之中,好像標準C++并不會(huì )給出operator =啊。等我去試一試。
gongminmin
當然會(huì )有默認的operator=了
按照c++標準,編譯器會(huì )生成五個(gè)默認成員函數:
默認構造函數
拷貝構造函數
析構函數
operator=
operator&
千里馬肝
class A
{
public:
A(int i) : m_i(i){}
int m_i;
};
分別說(shuō)說(shuō)吧:
1. A a = 0;
首先, compiler認為這樣寫(xiě)是不符合規矩的, 因為A = A才是正常行為。
但是她并不放棄, 通過(guò)搜索, 發(fā)現A可以根據一個(gè)int構造, 同時(shí)這個(gè)A(int i)沒(méi)有用explicit修飾過(guò)。
那么A a = 0; 這樣的一句話(huà)隨即轉變成:
A tmp(0);
A a = tmp;
需要說(shuō)明的是, A a = tmp是調用的copy ctor, 雖然class A中并沒(méi)有, 但是通常不寫(xiě)copy ctor的話(huà),
compiler都會(huì )生成一個(gè)memberwise assignment操作性質(zhì)的ctor, 底層實(shí)現通常會(huì )以memcpy進(jìn)行。
2. a = 10;
首先, 這樣同ctor的情況一樣, compiler無(wú)法直接進(jìn)行操作。
類(lèi)推, 等同于代碼:
A tmp(10);
a = tmp;
需要注意的是, a = tmp是調用的assignment操作, 同ctor一樣,我們自己不寫(xiě), 編譯器同樣進(jìn)行
memberwise assignment操作。
3. fn(A a)
同樣, fn(10)也是不對的, 但是"按照慣例", 呵呵, 會(huì )有:
A tmp(10);
fn(tmp);
另外, 為你解惑:
copy ctor的寫(xiě)法只能是T::T(const T &);
而assignment的寫(xiě)法可以多變, 即任意. 以T為例,
可以有
T &operator = (int n);
也可有
T &operator = (const char *);
當然, 你要確認如此的定義是對T而言有意義.
然后, 上述a = tmp, 即調用的默認的、標準的、自動(dòng)生成的T &operator = (const T &).
開(kāi)銷(xiāo)是會(huì )有一個(gè)臨時(shí)的A tmp生成, 然后memcpy.
但如果你自已寫(xiě)了T &operator = (int n), 那么a = 10即意味著(zhù)a.m_i = 10.
當然, 以開(kāi)銷(xiāo)而言要視你的T &operator = (int n)是否為inline了.
對于explicit, 當修飾explicit A(int i) : m_i(i){}, 那么即告訴compiler不要在私底下做那么多的轉換動(dòng)作.
而且自動(dòng)生成如A tmp(0)這樣的東西是我們不想要的, 因為某些情況下自動(dòng)轉換這種行為是錯誤的.
最后, 相關(guān)此類(lèi)問(wèn)題, 還有一個(gè)話(huà)題, 即class A可以有operator int(), 會(huì )在
fn(int n){}
A a(3);
fn(a)
起到魔術(shù)般的作用. 關(guān)于這個(gè), 留給你自己看看書(shū)吧:)
最后,祝學(xué)習C++的路上一帆風(fēng)順。Good luck~