【C++注意事项】7 Library vector Type

List Initializer or Element Count?

In a few cases, what initialization means depends upon whether we use curly braces or parentheses to pass the initializer(s). For example, when we initialize a vector< int > from a single int value, that value might represent the vector’s size or it might be an element value. Similarly, if we supply exactly two int values, those values could be a size and an initial value, or they could be values for a two-element vector. We specify which meaning we intend by whether we use curly braces or parentheses:

vector<int> v1(10);  // v1 has ten elements with value 0
vector<int> v2{10};  // v2 has one elements with value 10
vector<int> v3(10,1);  // v3 has tem elements with vlaue 1
vector<int> v4{10,1};  // v4 has two elements with values 10 and 1

When we use parentheses, we are saying that the values we supply are to be used to construct the object. Thus, v1 and v 3 use their initializers to determine the vector’s size, and its size and element values, respectively.

When we use curly braces, {…}, we’re saying that, if possible, we want to list initialize the object. That is, if there is a way to use the values inside the curly braces as a list of element initializers, the class will do so. Only if it is not possible to list initialize the object will the other ways to initialize the object be considered. The values we supply when we initialize v2 and v4 can be used as element values. These objects are list initialized; the resulting vectors have one and two elements, respectively.

On the other hand, if we use braces and there is no way to use the initializers to list initialize the object, then those values will be used to construct the object. For example, to list initialize a vector of strings, we must supply values that can be used as strings. In this case, there is no confusion about whether to list initialize the elements or constructs a vector of the given size:

vector<string> v5{"hi"};  // list initialization: v5 has one element
vector<string> v6("hi");  // error: can‘t construct a vector from a string literal
vector<string> v7{10};  // v7 has ten default-initialized elements
vector<string> v8{10,"hi"};  // v8 has tem elements with value "hi"

Although we used braces on all but one of these definitions, only v5 is list initialized. In order to list initialize the vector, the values inside braces must match the element type. We can’t use an int to initialize a string, so the initializers for v7 and v8 can’t be element initializers. If list initialization isn’t possible, the compiler looks for other ways to initialize the object from the given values.

Adding Elements to a vector

As one example, if we need a vector with values from 0 to 9, we can easily use list initialization. What if we wanted elements from 0 to 99 or 0 to 999 ? List initialization would be too unwieldy. In such cases, it is better to create an empty vector and use a vector member named push_back to add elements at run time.

The push_back operation takes a value and “pushes” that value as a new last element onto the “back” of the vector.

vector<int> v2;  // empty vector
for(int i=0; i!= 100; ++i)
    v2.push_back(i);  // append sequential integers to v2
// at end of loop v2 has 100 elements, values 0 ... 99

We use the same approach when we want to create a vector where we don’t know until run time how many elements the vector should have. For example, we might read the input, storing the values we read in the vector:

// read words from the standard input and store them as elements in a vector
string word;
vector<string> text;  // empty vector
while(cin>> word)
    text.push_back(word);  // append word to text

Again, we start with an initially empty vector. This time, we read and store an unknown number of values in text.

Starting with an empty vector and adding elements at run time is distinctly different from how we use built-in arrays in C and in most other languages. In particular, if you are accustomed to using C or Java, you might expect that it would be best to define the vector at its expected size. In fact, the contrary is usually the case.

Other vector Operations

In addition to push_back, vector provide only a few other operations, most of which are similar to the corresponding operations on strings.

Operations Notes
v.empty() Returns true if v is empty; otherwise returns false.
v.size() Returns the number of elements in v.
v.push_back(t) Adds an element with value t to end of v.
v[n] Returns a reference to the element at position n in v.
v1=v2 Replaces the elements in v1 with a copy of the elements in v2.
v1={a,b,c…} Replaces the elements in v1 with a copy of the elements in the comma-separated list.
v1==v2,v1!=v2 v1 and v2 are equal if they have the same number of elements and each element in v1 is equal to the corresponding element in v2.
<, <=, >, >= Have their normal meaning using dictionary ordering.

We access the elements of a vector the same way that we access the characters in a string: through their position in the vector. For example, we can use a range for to process all the elements in a vector:

vector<int> v{1,2,3,4,5,6,7,8,9};
for(auto &i: v)  // for each element is v (note: i is a reference)
    i*= i;  // square the element value
for(auto i: v)  // for each element in v
    cout<< i << " ";  // print the element
cout<<endl;

The output should be

1 4 9 16 25 36 49 64 81

To use size_type, we must name the type in which it is defined. A vector type always includes its element type:

vector<int>:: size_type  // ok
vector::size_type  // error

Subscripting Does Not Add Elements

Programmers new to C++ sometimes think that subscripting a vector adds elements; it does not. The following code intends to add tem elements to ivec:

vector<int> ivec;  // empty vector
for(decltype(ivec.size()) ix= 0; ix!= 10; ++ix)
    ivec[ix]= ix;  // disaster: ivec has no elements

However, it is in error: ivec is an empty vector; there are no elements to subscript! As we’ve seen, the right way to write this loop is to use push_back:

for(decltype(ivec.size()) ix= 0; ix!= 10; ++ix)
    ivec.push_back(ix);  // ok: adds a new element with value x

The subscript operator on vector (and string) fetches an existing element; it does not add an element.

Subscript Only Elements that are Known to Exist!

It is crucially important to understand that we may use the subscript operator (the [] operator) to fetch only elements that actually exist. For example,

vector<int> ivec;  // empty vector
cout<< ivec[10];  // error: ivec has no elements!
vector<int> ivec2(10);  // vector with ten elements
cout<< ivec2[10];  // error: ivec2 has elements 0...9

It is an error to subscript an element that doesn’t exist, but it is an error that the compiler is unlikely to detect. Instead, the value we get at run time is undefined.

Attempting to subscript elements that do not exist is, unfortunately, an extremely common and pernicious programming error. So-called buffer overflow errors are the result of subscripting elements that don’t exist. Such bugs are the most common cause of security problems in PC and other applications.

时间: 2024-10-14 02:58:33

【C++注意事项】7 Library vector Type的相关文章

C++学习:关于“std::vector&lt;Type&gt;::iterator”的一个错误

在类模板里面定义如下迭代器: template<class Type> class className { private: vector<Type>::iteratoriter; }; 则会出现如下图所示的错误: 这是由于:vector本身就是模板,在其模板参数未确定之前,也就是Type 的具体类型没有确定之前,这个Type是未知的. 解决方法如下: template<class Type> class className { private: typename ve

【C++注意事项】6 Library string Type

Processing Every Character? Use Range-Based for If we want to do something to every character in a string, by far the best approach is to use a statement introduced by the new standard: the range for statement. This statement iterates through the ele

nomasp 博客导读:Android、UWP、Algorithm、Lisp(找工作中……

Profile Introduction to Blog 您能看到这篇博客导读是我的荣幸.本博客会持续更新.感谢您的支持.欢迎您的关注与留言.博客有多个专栏,各自是关于 Android应用开发 .Windows App开发 . UWP(通用Windows平台)开发 . SICP习题解 和 Scheme语言学习 . 算法解析 与 LeetCode等题解 .而近期会加入的文章将主要是算法和Android.只是其他内容也会继续完好. About the Author 独立 Windows App 和

C++学习书籍推荐《C++ Primer 第五版 (英文)》下载

百度云及其他网盘下载地址:点我 编辑推荐 <C++ Primer(英文版)(第5版)>是全球最畅销的C++图书.这本久负盛名的C++经典教程,时隔八年之久,终迎来的重大升级.除令全球无数程序员从中受益,甚至为之迷醉的--C++大师Stanley B. Lippman的丰富实践经验,C++标准委员会原负责人Josée Lajoie对C++标准的深入理解,以及C++先驱Barbara E.Moo在C++教学方面的真知灼见外,更是基于全新的C++11标准进行了全面而彻底的内容更新.非常难能可贵的是,

C++STL中的vector

vector 容器 vector是C++标准模版库(STL,Standard Template Library)中的部分内容.之所以认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单的说:vector是一个能够存放任意类型的动态数组,能够增加和压缩数据. 使用vector容器之前必须加上<vector>头文件:#include<vector>; vector属于std命名域的内容,因此需要通过命名限定:using std::vector;也可以直接使用全局的命名空间方式

STL容器之一vector

STL中最简单也是最有用的容器之一是vector<T>类模板,称为向量容器,是序列类型容器中的一种. 容器容量可以选择性修改.(1)声明:vector<type>  v;    //容量为0构造v对象,指定元素类型为typevector<type>  v(n);    //容量为n构造v对象,指定元素类型为typevector<type>  v(n, initValue);    //容量为n构造v对象,指定元素类型为type,且所有元素被初始化为initV

.NET 中,编译器直接支持的数据类型称为基元类型(primitive type).基元类型和.NET框架类型(FCL)中的类型有直接的映射关系.

.NET 中,编译器直接支持的数据类型称为基元类型(primitive type).基元类型和.NET框架类型(FCL)中的类型有直接的映射关系. The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single. https://msdn.microsoft.com/zh-cn/library/s

STL之vector

今天学习了STL 以前用的c,可是比赛回来发现c有点弱,c++的stl是比较实用的,适合比赛.所以学习了一下. vector. 这是一个容器,其实就是线性表. 使用之前在头部加上#include <vector> 然后就可以使用 vector<type> vec; //type is a kind of basic type (eg. int double ..) 然后访问这个表的时候需要声明一个变量 vector<type>::iterator ite; 然后就可以用

vector内存

一.vector的内存增长 vector内存的特点:内存空间只会增长,不会减少 vector支持随机访问,vector容器的元素以连续的方式存放,每个元素都紧挨着前一个元素存储.当vector插入数据时,可能空间不够,这时要重新分配新的内存,将数据从旧空间拷贝到新空间,然后释放旧空间,这样性能难以接受,因此每次对vector进行内存分配时,其实际分配的容量要比当前所需的空间多一些.就是说vector预留了一些额外的存储区,用于存放新添加的元素,这样就不必为每个新元素重新分配这个容器的空间.当预留