在C++ 98中,std::vector填充构造函数的原型具有初始化程序的默认值.
explicit vector (size_type n, const value_type& val = value_type(),
const allocator_type& alloc = allocator_type());
Run Code Online (Sandbox Code Playgroud)
C++ 11使用两个原型.
explicit vector (size_type n);
vector (size_type n, const value_type& val,
const allocator_type& alloc = allocator_type());
Run Code Online (Sandbox Code Playgroud)
(在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
}
Run Code Online (Sandbox Code Playgroud)
Yak*_*ont 51
C++ 98采用了原型对象,然后复制了n次.默认情况下,原型是默认构造的对象.
C++ 11版本构造了n个默认构造的对象.
这消除了n个副本并用n个default-constructions替换它.此外,它避免了构建原型.
假设你的班级看起来像这样:
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;
}
};
Run Code Online (Sandbox Code Playgroud)
这是一个总是拥有1000 ints 缓冲区的类.
如果我们然后创建一个矢量bulky:
std::vector<bulky> v(2);
Run Code Online (Sandbox Code Playgroud)
在C++ 98中,这分配了3次1000个整数.在C++ 11中,这只分配了1000次整数.
此外,C++ 98版本要求该类型可以复制.C++ 11中有不可复制的类型,例如std::unique_ptr<T>,并且vector使用C++ 98签名无法生成一个默认构造的唯一指针.C++ 11签名没有任何问题.
std::vector<std::unique_ptr<int>> v(100);
Run Code Online (Sandbox Code Playgroud)
如果我们还有C++ 98版本,上面的代码将不起作用.
How*_*ant 47
构造函数分为两部分的原因是支持"仅移动"类型,如unique_ptr<T>.
这个构造函数:
vector(size_type n, const T& value, const Allocator& = Allocator());
Run Code Online (Sandbox Code Playgroud)
需要T复制可构造,因为n T必须复制s才能value填充vector.
这个构造函数:
explicit vector(size_type n, const Allocator& = Allocator());
Run Code Online (Sandbox Code Playgroud)
它不要求T是可复制构造,只有缺省构造.
后一个构造函数适用于unique_ptr<T>:
std::vector<std::unique_ptr<int>> s(5);
Run Code Online (Sandbox Code Playgroud)
而前一个构造函数没有.
以下是进行此更改的提案:http: //www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1858.html#23.2.4.1%20-%20vector%20constructors,%20copy ,%20于是%20assignment
本文有一些基本原理,但无疑是简洁的一点:http: //www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1771.html
FWIW, resize:
void resize(size_type sz, T c = T());
Run Code Online (Sandbox Code Playgroud)
被分成:
void resize(size_type sz);
void resize(size_type sz, const T& c);
Run Code Online (Sandbox Code Playgroud)
出于同样的原因.第一个需要默认的可构造但不能复制可构造(以支持默认的可构造移动类型),第二个需要复制可构造.
这些更改不是100%向后兼容.对于某些类型(例如,引用计数的智能指针),从默认构造对象的复制构造与默认构造不同.然而,支持仅移动类型的好处被认为是值得这个API破坏的成本.