[英]Why was the constructor interface of std::vector changed with C++11?
[英]Why did C++11 remove the default value from the prototypes of std::vector's fill constructor?
在C ++ 98中, std::vector
的fill構造函數的原型具有初始化程序的默認值。
explicit vector (size_type n, const value_type& val = value_type(),
const allocator_type& alloc = allocator_type());
C ++ 11使用兩個原型。
explicit vector (size_type n);
vector (size_type n, const value_type& val,
const allocator_type& alloc = allocator_type());
(在C ++ 14中,填充構造函數再次更改,但這不是這個問題的重點。)
參考鏈接在這里 。
為什么C ++ 11不贊成使用默認的初始化值value_type()
?
順便說一句,我嘗試使用clang++ -std=c++11
編譯以下代碼,並發出錯誤,這意味着值類型仍需要具有默認構造函數,例如S() {}
,即是默認可構造的。
#include <vector>
struct S {
int k;
S(int k) : k(k) {} // intentionally remove the synthesized default constructor
};
int main() {
std::vector<S> s(5); // error: no matching constructor
}
C ++ 98提取了一個原型對象,然后將其復制了n次。 默認情況下,原型是默認構造的對象。
C ++ 11版本構造了n個默認構造的對象。
這消除了n個副本,並用n個默認構造替換了它。 另外,它避免了構建原型。
假設您的課程如下所示:
struct bulky {
std::vector<int> v;
bulky():v(1000) {} // 1000 ints
bulky(bulky const&)=default;
bulky& operator=(bulky const&)=default;
// in C++11, avoid ever having an empty vector to maintain
// invariants:
bulky(bulky&& o):bulky() {
std::swap(v, o.v);
}
bulky& operator=(bulky&& o) {
std::swap(v,o.v);
return *this;
}
};
這是一個始終擁有1000
int
的緩沖區的類。
如果然后創建一個bulky
的向量:
std::vector<bulky> v(2);
在C ++ 98中,這分配了3次1000整數。 在C ++ 11中,它僅分配2乘以1000整數。
另外,C ++ 98版本要求該類型是可復制的。 C ++ 11中有不可復制的類型,例如std::unique_ptr<T>
,並且不能使用C ++ 98簽名生成默認構造的唯一指針vector
。 C ++ 11簽名沒有問題。
std::vector<std::unique_ptr<int>> v(100);
如果我們仍然具有C ++ 98版本,則上述方法將無效。
構造函數一分為二的原因是為了支持“僅移動”類型,例如unique_ptr<T>
。
此構造函數:
vector(size_type n, const T& value, const Allocator& = Allocator());
要求T
是可復制構造的,因為必須從value
復制n
T
s才能填充vector
。
此構造函數:
explicit vector(size_type n, const Allocator& = Allocator());
不需要 T
是可復制構造,只有缺省構造。
后一個構造函數與unique_ptr<T>
:
std::vector<std::unique_ptr<int>> s(5);
而前一個構造函數則沒有。
這是進行此更改的提案: http : //www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1858.html#23.2.4.1%20-%20vector%20constructors,%20copy ,%20和%20分配
而且,盡管具有一些基本原理,但本文還是有一些基本依據: http : //www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1771.html
Fwiw, resize
:
void resize(size_type sz, T c = T());
分為:
void resize(size_type sz);
void resize(size_type sz, const T& c);
出於完全相同的原因。 第一個需要默認可構造但不可復制構造(以支持默認可構造僅移動類型),第二個需要可復制構造。
這些更改並非100%向后兼容。 對於某些類型(例如,引用計數的智能指針),默認構造對象的副本構造與默認構造不同。 但是,支持僅移動類型的好處被認為值得此API損壞的代價。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.