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 类提供了实现可增长数组的功能,随着更多元素加入其中,数组变的更大。在删除一些元素之后,数组变小。

Vector 有三个构造函数:
public Vector(int initialCapacity,int capacityIncrement)
public Vector(int initialCapacity)
public Vector()

Vector 运行时创建一个初始的存储容量initialCapacity,存储容量是以capacityIncrement 变量定义的增量增长。初始的存储容量和capacityIncrement 可以在Vector 的构造函数中定义。第二个构造函数只创建初始存储容量。第三个构造函数既不指定初始的存储容量也不指定capacityIncrement。
Vector 类提供的访问方法支持类似数组运算和与Vector 大小相关的运算。类似数组的运算允许向量中增加,删除和插入元素。它们也允许测试矢量的内容和检索指定的元素,与大小相关的运算允许判定字节大小和矢量中元素不数目。
希望能解决您的问题。追问

谢谢了!但是你的回答没有回答
到我提的疑问

参考技术A 因为你一开始定义myint时候,只是生成了一个对象myint,具体里面存储的只是一个指针,而不是真正的int类型数组,没有分配内存空间也就无法赋值,pushback函数就会申请新的内存空间生成新数组存储赋的值,理解了吗?追问

如果这样说确实可以解释通了。
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;
  
;

这是一个总是拥有1000ints缓冲区的类。

如果我们随后创建bulky 的向量:

std::vector<bulky> v(2);

在 C++98 中,这分配了 3 次 1000 个整数。在 C++11 中,这仅分配 2 乘以 1000 个整数。

另外,C++98 版本要求类型是可复制的。 C++11中有不可复制的类型,比如std::unique_ptr&lt;T&gt;,使用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&amp; value = T(), const Allocator&amp; = Allocator()); 被拆分为两个explicit vector(size_type n); vector(size_type n, const T&amp; value, const Allocator&amp; = Allocator());。基本上,在 C++98 中,将元素放入向量中的唯一方法是复制它们。【参考方案2】:

构造函数被分成两部分的原因是为了支持“只移动”类型,例如unique_ptr&lt;T&gt;

这个构造函数:

vector(size_type n, const T& value, const Allocator& = Allocator());

要求T 是可复制构造的,因为必须从value 复制n Ts 才能填充vector

这个构造函数:

explicit vector(size_type n, const Allocator& = Allocator());

要求T 是可复制构造的,只有默认可构造的。

后一个构造函数与unique_ptr&lt;T&gt;一起工作:

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&lt;T&gt; 是不可复制类的一个很好的例子。不幸的是,只能接受一个答案。 这似乎是真正的答案,因为它解释了为什么这样做了。 (Yakk 目前接受的答案也提到了它,但顺便说一句。) 他们不能只是enable_ifis_copy_constructible吗? @Mehrdad:本来可以的。我判断 container&lt;T&gt;(n) 的 C++11 行为实际上通常更可取,如果确实需要 C++98 行为,那么语法 container&lt;T&gt;(n, T) 仍然可用。并且在绝大多数情况下没有语义差异(大多数用例不会改变)。有一些风险,但有更大的好处。事后看来,我认为这场赌博奏效了。

以上是关于vector 构造函数的主要内容,如果未能解决你的问题,请参考以下文章

vector构造函数的学习

在不调用构造函数的情况下创建 Vector 元素

如何将 <vector> 与构造函数一起使用

使用 std::vector 时如何将索引信息传递给元素构造函数?

vector 3 构造 析构

在类构造函数中设置 std::vector