vector 构造函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vector 构造函数相关的知识,希望对你有一定的参考价值。
为什么vector<int > myint;这种方式定义myint,是不可以使用下标方式赋值
但是一旦里面有值了就可以呢?
下面代码是正确的
#include<iostream>
#include<vector>
using namespace std;
void main()
vector<int> myint ;
for(int i=0;i<10;i++)
myint.push_back(20-i);
for(int i=0;i<10;i++)
cout<<myint[i]<<" ";
cout<<endl;
for(int i=0;i<10;i++)
myint[i]=i+5;
for(int i=0;i<10;i++)
cout<<myint[i]<<" ";
但是这样就是错误的
#include<iostream>
#include<vector>
using namespace std;
void main()
vector<int> myint ;
for(int i=0;i<10;i++)
myint[i]=i+5;
for(int i=0;i<10;i++)
cout<<myint[i]<<" ";
Vector 有三个构造函数:
public Vector(int initialCapacity,int capacityIncrement)
public Vector(int initialCapacity)
public Vector()
Vector 运行时创建一个初始的存储容量initialCapacity,存储容量是以capacityIncrement 变量定义的增量增长。初始的存储容量和capacityIncrement 可以在Vector 的构造函数中定义。第二个构造函数只创建初始存储容量。第三个构造函数既不指定初始的存储容量也不指定capacityIncrement。
Vector 类提供的访问方法支持类似数组运算和与Vector 大小相关的运算。类似数组的运算允许向量中增加,删除和插入元素。它们也允许测试矢量的内容和检索指定的元素,与大小相关的运算允许判定字节大小和矢量中元素不数目。
希望能解决您的问题。追问
谢谢了!但是你的回答没有回答
到我提的疑问
如果这样说确实可以解释通了。
ok,就这样理解了。
当然是这么理解,这个类被封装了,你不能看到里面的东西,不过你可以猜测他是怎么样实现的
本回答被提问者采纳为啥 C++11 会从 std::vector 填充构造函数的原型中移除默认值?
【中文标题】为啥 C++11 会从 std::vector 填充构造函数的原型中移除默认值?【英文标题】:Why did C++11 remove the default value from the prototypes of std::vector's fill constructor?为什么 C++11 会从 std::vector 填充构造函数的原型中移除默认值? 【发布时间】:2018-02-06 03:41:52 【问题描述】:在 C++98 中,std::vector
的填充构造函数的原型具有初始值设定项的默认值。
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 中,填充构造函数再次更改,但这不是这个问题的重点。)
参考链接是here。
为什么 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++11 之前也不会工作,因为S
不是默认可构造的。而且 C++11 并没有弃用默认值,那个单一的构造函数被另外两个替换了。
默认值是邪恶的。
@Praetorian 是的,我应该说 C++11 删除了构造函数原型中的默认值。
@Jesper Juhl 你得详细说明
【参考方案1】:
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
s缓冲区的类。
如果我们随后创建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 版本,上面的方法就行不通了。
【讨论】:
我可能会恢复解释,因为正确性胜过效率 :D 但是,这是对好问题的好答案。 @SergeyA 我不确定何时确切地要求在向量中从传递给向量的类型放宽,而是与所使用的确切方法耦合。效率差异肯定出现在 C++11 中;我不确定从技术上讲,放宽的要求是否有效。所以我详细说明了我所知道的,然后提到在 C++11/14 的某个地方它也导致了对类型的放宽要求(实际上在 C++11 中,我不确定标准是否真的在 C+ 之前放宽了它+14,因为我不记得了) 很好的解释,我只是不明白为什么在 c++98 版本中原型对象不用作第一个元素(即,在您的示例中也只会分配 2000 个整数) @tobi303 原型存在于堆栈中,在参数中。对象存在于由向量管理的内存中。向量不管理参数,因此它不能是向量中的第一个对象。 C++ 具有值语义,该对象具有确定的位置。在 C++11 中,他们可以将其设为右值或左值参数并从中移出,但我疯狂的bulky
类型即使在移出时也拒绝为空,因此它也无济于事。
@Yakk 在 C++11 中放宽了。 C++98 中的explicit vector(size_type n, const T& value = T(), const Allocator& = Allocator());
被拆分为两个explicit vector(size_type n); vector(size_type n, const T& value, const Allocator& = Allocator());
。基本上,在 C++98 中,将元素放入向量中的唯一方法是复制它们。【参考方案2】:
构造函数被分成两部分的原因是为了支持“只移动”类型,例如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,%20and%20assignment
这篇论文有一些基本原理,尽管无可否认有点简洁: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 破坏付出代价。
【讨论】:
好点。unique_ptr<T>
是不可复制类的一个很好的例子。不幸的是,只能接受一个答案。
这似乎是真正的答案,因为它解释了为什么这样做了。 (Yakk 目前接受的答案也提到了它,但顺便说一句。)
他们不能只是enable_if
is_copy_constructible
吗?
@Mehrdad:本来可以的。我判断 container<T>(n)
的 C++11 行为实际上通常更可取,如果确实需要 C++98 行为,那么语法 container<T>(n, T)
仍然可用。并且在绝大多数情况下没有语义差异(大多数用例不会改变)。有一些风险,但有更大的好处。事后看来,我认为这场赌博奏效了。以上是关于vector 构造函数的主要内容,如果未能解决你的问题,请参考以下文章