標籤:

C++ 03和C++11的vector在調用元素的構造函數時有什麼區別?

考慮以下C++代碼:

#include &
#include &
using std::vector;

class A
{
public:
A(const char* s = "1234") { printf("ASDF
"); fflush(stdout); }
};

int main()
{
vector& av(5);
printf("%u
", av.size());
return 0;
}

這個代碼,在C++03和C++11(14)模式下,似乎行為不同。

用g++(5.1)/clang(3.7)編譯時,如果以默認的C++03模式編譯,只會列印一個ASDF,指定-std=c++11或者-std=c++14後,會列印5個。用VC 2015編譯,會列印5個。

經排查,這個差別應該只和編譯時的語言標準有關,和優化無關。不加優化參數、-O0,-O,-O2,-O3,-Os都是一個結果。

這是什麼原因造成了這個區別?


@egmkang wang 猜對了一半。

不過他的說法中,會有二義性重載,編譯會出錯。

事實是,這個構造函數的簽名在C++11 就已經改掉了。

C++98/03 的時候是

explicit vector(size_type count, const T value = T(),
const Allocator alloc = Allocator());

C++11 是

vector( size_type count, const T value,
const Allocator alloc = Allocator());
explicit vector( size_type count );

C++14 是

vector( size_type count, const T value,
const Allocator alloc = Allocator());
explicit vector(size_type count, const Allocator alloc = Allocator());


C++98/03和C++11匹配的構造函數不一樣,libstdc++: vector Source File

82 #if __cplusplus &>= 201103L
83 explicit
84 vector(size_type __n, const _Allocator __a = _Allocator())
85 : _Base(__n, __a), _M_guaranteed_capacity(__n) { }
86
87 vector(size_type __n, const _Tp __value,
88 const _Allocator __a = _Allocator())
89 : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
90 #else
91 explicit
92 vector(size_type __n, const _Tp __value = _Tp(),
93 const _Allocator __a = _Allocator())
94 : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { }
95 #endif

參考std::vector::vector,

explicit vector( size_type count,
const T value = T(),
const Allocator alloc = Allocator());
(until C++11)
explicit vector( size_type count,
const T value,
const Allocator alloc = Allocator());
(since C++11)
explicit vector( size_type count );
(since C++11)
(until C++14)
explicit vector( size_type count, const Allocator alloc = Allocator() ); (since C++14)

C++98/03匹配的是第一種,而C++11是第三種,標準有規定。

如果你的代碼改成

int main()
{
vector& av(5, A());
printf("%u
", av.size());
return 0;
}

這樣的話,你用C++11也會匹配到第一種構造函數,也只出現一個ASDF,但是這樣的話會如同C++98/03一樣有拷貝,然而第三種構造函數是沒有拷貝的。


參考 std::vector::vector,C++ 11更改了vector構造函數的介面,不使用默認實參了。

// (until C++11)
// C++ 03 調用的構造函數
// 先構造一個默認值,然後複製5個(調用的是複製構造函數),所以列印一次
explicit vector( size_type count,
const T value = T(),
const Allocator alloc = Allocator());

// (since C++11)
// C++ 11 調用的構造函數
// 直接調用默認構造函數構造5次,所以列印5個
explicit vector( size_type count );


vector有一個vector(size_t size)vector(size_t size, const T value = T()), 看樣子編譯器匹配到了後者. 個人感覺編譯器匹配哪一個都沒問題, 不知道標準有沒有規定必須得匹配到後者.

PS:

仔細看了一下cppreference. vector(size_t size, const T value = T())這個API是until C++11, vector(size_t size, const T value)是since C++11.

vector(size_t size)這個C++14裡面也幹掉了, 換成帶alloc的了.


推薦閱讀:

為什麼C++ 中 void * 能指向靜態成員函數但不能指非靜態向成員函數?
程序員對自己的語言有沒有感情的?
蘋果系統為什麼用Objective-C,而不用C++?
為什麼盡量不要使用using namespace std?
如何delete數組?

TAG:C | C11 |