C++ STL之vector

C++STLvector容器的使用方法

1      成员类型...1

2      vector的构造函数...2

2.1  右值和引用...3

2.2   初始化列表构造函数...3

2.3   赋值函数...5

容量相关的函数...5

3.1   size 函数...6

3.2   max_size函数...6

3.3   resize函数...6

3.4   capacity函数...7

3.5   reverse函数...7

3.6   empty函数...8

3.7   shrink_to_fit 函数...8

  vector元素获取函数...8

4.1  []操作符函数...9

4.2  at函数...9

4.3  front函数...9

4.4  back 函数...9

4.5  data 函数C++11.9

5      vector中修改元素的函数...9

5.1   assign 函数...9

5.2   push_back 函数...10

5.3   pop_back 函数...10

5.4   insert 函数...10

5.5   erase 函数...11

5.6   swap 函数...12

5.7   emplace 函数(C++11...12

5.8   emplace_back 函数...13

6      关于分配器的函数...13

7      关于迭代器的函数...14

Vector 本质上也是数组,它和array的区别是array的长度大小固定,而vector是容量可以动态变化的数组。当有新元素插入时,需要重新非配内存,这会造成时间上昂贵的开销,但是实际上,vector实际上被分配一些额外的存贮空间以应对元素个数增长,因此vector实际容量的大小比它应该包含元素所需的内存大些。库函数都用相对应的策略来应对时间上的消耗以及空间的分配,当元素在末尾插入时,由于额外存储空间的原因,消耗的时间是常量复杂度,只有当插入的元素城指数增长时,才需要重新分配内存。

相对array来讲,由于vector增加了动态分配内存,所以vector在需要更多的内存。相对listdequeforward_listvector由于是顺序存储,所以其访问速度比这些动态分配内存的容器快,在末尾添加和删除元素也相对较快,

   成员类型

allocator_type

A type that represents the allocator class for the vector object.

const_iterator

A type that provides a random-access iterator thatcan read aconst element in a vector.

const_pointer

A type that provides a pointer toa const element in a vector.

const_reference

A type that provides a reference toa const element stored in a vector for reading andperforming const operations.

const_reverse_iterator

A type that provides a random-access iterator thatcan read anyconst element in the vector.

difference_type

A type that provides the difference between theaddresses of two elements in a vector.

iterator

A type that provides a random-access iterator thatcan read or modify any element in a vector.

pointer

A type that provides a pointer to an element in avector.

reference

A type that provides a reference to an elementstored in a vector.

reverse_iterator

A type that provides a random-access iterator thatcan read or modify any element in a reversed vector.

size_type

A type that counts the number of elements in avector.

value_type

A type that represents the data type stored in avector.

这些东西所有的容器都大同小异,在前面已经介绍过了。

 vector的构造函数

Vector的构造函数分两个版本种类的

98版本的

default (1)

explicit vector (const allocator_type& alloc =allocator_type());

fill (2)

explicit vector (size_type n, constvalue_type& val = value_type(),

                const allocator_type& alloc = allocator_type());

range (3)

template

        vector (InputIterator first, InputIterator last,

                const allocator_type& alloc = allocator_type());

copy (4)

vector (const vector& x);

以上四个构造函数分部是默认构造函数,填充构造函数,范围构造函数,复制构造函数

11版的

Default(1)

explicit vector (const allocator_type& alloc =allocator_type());

fill (2)

explicit vector (size_type n);

        vector (size_type n, const value_type& val,

                const allocator_type& alloc = allocator_type());

range (3)

template

vector (InputIterator first, InputIteratorlast,

       const allocator_type& alloc = allocator_type());

copy (4)

vector (const vector& x);

vector (const vector& x, constallocator_type& alloc);

move (5)

vector (vector&& x);

vector (vector&& x, constallocator_type& alloc);

initializer list (6)

vector (initializer_list il,

const allocator_type& alloc =allocator_type());

这里多了两个构造函数,

一个是move构造函数,一个是初始化列表的构造函数。关于move构造函数,这个是C++11中的新的语法,

2.1 右值和引用

C++03及之前的标准,临时对象(称为右值"R-values",位于赋值运算符之右)无法被改变,在 C中亦同(且被视为无法和 const T& 做出区分)。尽管在某些情况下临时对象的确会被改变,甚至也被视为是一个有用的漏洞。

C++11 增加一个新的非常数引用(reference)类型,称作右值引用(R-valuereference),标记为T&&。右值引用所引用的临时对象可以在该临时对象被初始化之后做修改,这是为了允许move 语义。

C++03 性能上被长期被诟病的其中之一,就是其耗时且不必要的深度拷贝。深度拷贝会发生在当对象是以传值的方式传递。举例而言,std::vector 是内部保存了 C-style 数组的一个包装,如果一个std::vector的临时对象被建构或是从函数返回,要将其存储只能通过生成新的std::vector并且把该临时对象所有的数据复制进去。该临时对象和其拥有的内存会被摧毁。(为了讨论上的方便,这里忽略返回值优化)

C++11,一个std::vector "move 构造函数"对某个vector的右值引用可以单纯地从右值复制其内部 C-style 数组的指针到新的 vector,然后留下空的右值。这个操作不需要数组的复制,而且空的临时对象的析构也不会摧毁内存。传回vector临时对象的函数不需要显式地传回std::vector&&。如果vector没有move 构造函数,那么复制构造函数将被调用,以const std::vector &的正常形式。 如果它确实有move 构造函数,那么就会调用 move 构造函数,这能够免除大幅的内存配置。

基于安全的理由,具名的参数将永远不被认定为右值,即使它是被如此声明的;为了获得右值必须使用 std::move()

bool is_r_value(int &&) { return true; }
bool is_r_value(const int &) { return false; }
 
void test(int && i)
{
    is_r_value(i); // i 為具名變數,即使被宣告成右值也不會被認定是右值。
    is_r_value(std::move<</span>int&>(i)); // 使用 std::move() 取得右值。
}

2.2  初始化列表构造函数

标准C++C带来了初始化列表(initializer list)的概念。这个构想是结构或是数组能够依据成员在该结构内定义的顺序通过给予的一串引数来产生。这些初始化列表是递归的,所以结构的数组或是包含其他结构的结构可以使用它们。这对静态列表或是仅是把结构初始化为某值而言相当有用。C++有构造函数,能够重复对象的初始化。但单单只有那样并不足以取代这项特色的所有机能。在C++03中,只允许在严格遵守POD的定义和限制条件的结构及类型上使用这项机能,非POD的类型不能使用,就连相当有用的STL容器std::vector也不行。

C++11将会把初始化列表的概念绑到类型上,称作std::initializer_list。这允许构造函数或其他函数像参数般地使用初始化列表。举例来说:

class SequenceClass
{
public:
  SequenceClass(std::initializer_list<</span>int> list);
};

这将允许SequenceClass由一连串的整数构造,就像:

SequenceClass someVar = {1, 4, 5, 6};

这个构造函数是种特殊的构造函数,称作初始化列表构造函数。有着这种构造函数的类型在统一初始化的时候会被特别对待。

类型std::initializer_list<>是个第一级的C++11标准程序库类型。然而他们只能够经由C++11编译器通过{}语法的使用被静态地构造。这个列表一经构造便可复制,虽然这只是copy-by-reference。初始化列表是常数;一旦被创建,其成员均不能被改变,成员中的数据也不能够被变动。

因为初始化列表是真实类型,除了类型构造式之外还能够被用在其他地方。正规的函数能够使用初始化列表作为引数。例如:

void FunctionName(std::initializer_list<</span>float> list);
 
FunctionName({1.0f, -3.45f, -0.4f});

标准容器也能够以这种方式初始化:

vector<</span>string> v = { "xyzzy", "plugh", "abracadabra" };

标准C++ 在初始化类型方面有着许多问题。初始化类型有数种方法,而且交换使用时不会都产生相同结果。传统的建构式语法,看起来像是函数声明,而且为了能使编译器不会弄错必须采取一些步骤。只有集合体和POD 类型能够被集合式的初始化(使用 SomeType var = {};).

C++11 将会提供一种统一的语法初始化任意的对象,它扩充了初始化串行语法:

struct BasicStruct
{
 int x;
 float y;
};
 
struct AltStruct
{
  AltStruct(int _x, float _y) : x(_x), y(_y) {}
 
private:
  int x;
  float y;
};
 
BasicStruct var1{5, 3.2f};
AltStruct var2{2, 4.3f};

var1 的初始化的运作就如同 C-style 的初始化串行。每个公开的参数将被对应于初始化串行的值给初始化。隐式类型转换会在需要的时候被使用,这里的隐式类型转换不会产生范围缩限(narrowing)。要是不能够转换,编译便会失败。(范围缩限(narrowing):转换后的类型无法表示原类型。如将 32-bit 的整数转换为 16-bit 8-bit 整数,或是浮点数转换为整数。var2 的初始化则是简单地调用建构式。

统一的初始化建构能够免除具体指定特定类型的必要:

struct IdString
{
  std::string name;
  int identifier;
};
 
IdString var3{"SomeName", 4};

该语法将会使用 const char * 参数初始化 std::string 。你也可以做像下面的事:

IdString GetString()
{
  return {"SomeName", 4}; // 注意這裡不需要明確的型別
}

统一初始化不会取代建构式语法。仍然会有需要用到建构式语法的时候。如果一个类型拥有初始化串行建构式(TypeName(initializer_list);),而初始化串行符合sequence 建构式的类型,那么它比其他形式的建构式的优先权都来的高。C++11 版本的 std::vector 将会有初始化串行建构式。这表示:

std::vector<</span>int> theVec{4};

这将会调用初始化串行建构式,而不是调用std::vector只接受一个尺寸参数产生相应尺寸 vector 的建构式。要使用这个建构式,用户必须直接使用标准的建构式语法。

2.3  赋值函数

C++98 :(copy)vector& operator= (const vector& x);

C++11      copyvector& operator= (const vector&x);

(move)vector& operator= (vector&&x);

(initial)vector& operator= (initializer_listil)

这几个函数很简单了,不必要多做解释。

容量相关的函数

size                    Return size (public member function )

max_size          Return maximum size (public member function )

resize               Change size (public member function )

capacity            Return size of allocated storage capacity (public member function )

empty              Test whether vector is empty (public member function )

reserve             Request a change in capacity (public member function )

shrink_to_fit     Shrink to fit (public member function )

3.1   size函数

size_type size() const;

函数返回vector的存储元素的个数,而不是其实际的容量。示例:

#include 
#include 
int main ()
{
  std::vector<</span>int> myints;
  std::cout << "0. size: " << myints.size() << '\n';
  for (int i=0; i<10; i++) myints.push_back(i);
  std::cout << "1. size: " << myints.size() << '\n';
  myints.insert (myints.end(),10,100);
  std::cout << "2. size: " << myints.size() << '\n';
  myints.pop_back();
  std::cout << "3. size: " << myints.size() << '\n';
  return 0;
}
结果:0. size: 0
1. size: 10
2. size: 20
3. size: 19

3.2   max_size函数

size_type max_size() const;

函数返回vector能够容纳的最大元素个数

3.3  resize函数
void resize (size_type n, value_type val = value_type());
改变函数尺寸大小,如果n大于vector的尺寸,则按照val的值在vector的末尾插入值,如果n小于vector的尺寸,则把多余的尺寸在结尾弹出。
#include 
#include 
int main ()
{
  std::vector<</span>int> myvector;
  // set some initial content:
  for (int i=1;i<10;i++) myvector.push_back(i);
  myvector.resize(5);
  myvector.resize(8,100);
  myvector.resize(12);
  std::cout << "myvector contains:";
  for (int i=0;i
    std::cout << ' ' << myvector[i];
  std::cout << '\n';
  return 0;
}
3.4 capacity函数
size_type capacity() const;
返回vector中实际分配的内存大小。示例如下:
#include 
#include 
int main ()
{
  std::vector<</span>int> myvector;
  for (int i=0; i<100; i++) myvector.push_back(i);
  std::cout << "size: " << (int) myvector.size() << '\n';
  std::cout << "capacity: " << (int) myvector.capacity() << '\n';
  std::cout << "max_size: " << (int) myvector.max_size() << '\n';
  return 0;
}
结果:

size: 100

capacity: 128

max_size: 1073741823

3.5 reverse函数
void reserve (size_type n);
改变vector的容量大小,当vector的容量设定时,vector的容量不会因此动态分配。示例代码如下:
#include 
#include 
int main ()
{
  std::vector<</span>int>::size_type sz;
  std::vector<</span>int> foo;
  sz = foo.capacity();
  std::cout << "making foo grow:\n";
  for (int i=0; i<100; ++i) {
    foo.push_back(i);
    if (sz!=foo.capacity()) {
      sz = foo.capacity();
      std::cout << "capacity changed: " << sz << '\n';
    }
  }
  std::vector<</span>int> bar;
  sz = bar.capacity();
  bar.reserve(100);   // this is the only difference with foo above
  std::cout << "making bar grow:\n";
  for (int i=0; i<100; ++i) {
    bar.push_back(i);
    if (sz!=bar.capacity()) {
      sz = bar.capacity();
      std::cout << "capacity changed: " << sz << '\n';
    }
  }
  return 0;
}
结果:
making foo grow:
capacity changed: 1
capacity changed: 2
capacity changed: 4
capacity changed: 8
capacity changed: 16
capacity changed: 32
capacity changed: 64
capacity changed: 128
making bar grow:
capacity changed: 100
3.6  empty函数
bool empty() const;
vector为空则返回false,否则true
3.7  shrink_to_fit 函数 
void shrink_to_fit();
这个是C++11中的函数,改变vector的容量使其和vector的尺寸大小符合
#include 
#include 
int main ()
{
  std::vector<</span>int> myvector (100);
  std::cout << "1. capacity of myvector: " << myvector.capacity() << '\n';
  myvector.resize(10);
  std::cout << "2. capacity of myvector: " << myvector.capacity() << '\n';
  myvector.shrink_to_fit();
  std::cout << "3. capacity of myvector: " << myvector.capacity() << '\n';
  return 0;
}
结果:
1. capacity of myvector: 100
2. capacity of myvector: 100
3. capacity of myvector: 10
   vector元素获取函数




operator[]       Access element (public member function )

at                      Access element (public member function )

front                 Access first element (public member function )

back                           Access last element (public member function )

data                  Access data (public member function )

4.1  []操作符函数
reference operator[] (size_type n);
const_reference operator[] (size_type n) const;
获取vector中元素,这个和C中获取数组元素一样
4.2  at函数
reference at (size_type n);
const_reference at (size_type n) const;
获取vector中的元素,这个和[]的作用一样,不过和[]不同的是,at()函数要对数组的边界进行检查,如果越界就会抛出异常,但是[]不会。
4.3  front函数
reference front();
const_reference front() const;
返回vector中首个元素的引用
4.4  back 函数
 reference back();
const_reference back() const;
返回vector中末尾元素的引用
4.5  data 函数 C++11
value_type* data() noexcept;
const value_type* data() const noexcept;
返回指向vector内存的指针。
     vector中修改元素的函数

assign               Assign vector content (public member function )

push_back       Add element at the end (public member function )

pop_back                  Delete last element (public member function )

insert                Insert elements (public member function )

erase                 Erase elements (public member function )

swap                 Swap content (public member function )

clear                 Clear content (public member function )

emplace           Construct and insert element (public member function )

emplace_back  Construct and insertelement at the end (public member function )

 
5.1    assign 函数

range (1)

template

  void assign (InputIteratorfirst, InputIterator last);

fill (2)

void assign (size_type n, const value_type&val);

在C++11中多了一个 初始化列表的函数

initializer list (3)

void assign (initializer_list il);

函数重新设置vector的内容,替换之前的内容。示例;
#include 
#include 
int main ()
{
  std::vector<</span>int> first;
  std::vector<</span>int> second;
  std::vector<</span>int> third;
  first.assign (7,100);             // 7 ints with a value of 100
 
  std::vector<</span>int>::iterator it;
  it=first.begin()+1;
 
  second.assign (it,first.end()-1); // the 5 central values of first
 
  int myints[] = {1776,7,4};
  third.assign (myints,myints+3);   // assigning from array.
 
  std::cout << "Size of first: " << int (first.size()) << '\n';
  std::cout << "Size of second: " << int (second.size()) << '\n';
  std::cout << "Size of third: " << int (third.size()) << '\n';
  return 0;
}
结果:
Size of first: 7
Size of second: 5
Size of third: 3
5.2    push_back 函数
void push_back (const value_type& val);
void push_back (value_type&& val); (C++11)
在vector的末尾插入一个元素。
5.3    pop_back 函数
void pop_back();
在vector的末尾删除一个元素
5.4    insert 函数

single element (1)

iterator insert (const_iterator position, constvalue_type& val);

fill (2)

iterator insert (const_iterator position,size_type n, const value_type& val);

range (3)

template

iterator insert (const_iterator position,InputIterator first, InputIterator last);

move (4)

iterator insert (const_iterator position,value_type&& val);

initializer list (5)

iterator insert (const_iterator position,initializer_list il);

其中的move(4),initializer list(5) 是C++11中的函数
函数的作用就是在vector中插入一个或者多个元素,函数的返回值是指向插入新元素中的第一个的迭代器。示例:
#include 
#include 
int main ()
{
  std::vector<</span>int> myvector (3,100);
  std::vector<</span>int>::iterator it;
 
  it = myvector.begin();
  it = myvector.insert ( it , 200 );
  myvector.insert (it,2,300);
 
  // "it" no longer valid, get a new one:
  it = myvector.begin();
 
  std::vector<</span>int> anothervector (2,400);
  myvector.insert (it+2,anothervector.begin(),anothervector.end());
 
  int myarray [] = { 501,502,503 };
  myvector.insert (myvector.begin(), myarray, myarray+3);
 
  std::cout << "myvector contains:";
  for (it=myvector.begin(); it
    std::cout << ' ' << *it;
  std::cout << '\n';
 
  return 0;
}
结果:
myvector contains: 501 502 503 300 300 400 400 200 100 100 100
5.5    erase 函数
iterator erase (iterator position);
iterator erase (iterator first, iterator last);
函数移走vector中的一个或者一定范围内的元素。
#include 
#include 
int main ()
{
  std::vector<</span>int> myvector;
  // set some values (from 1 to 10)
  for (int i=1; i<=10; i++) myvector.push_back(i);
  // erase the 6th element
  myvector.erase (myvector.begin()+5);
  // erase the first 3 elements:
  myvector.erase (myvector.begin(),myvector.begin()+3);
  std::cout << "myvector contains:";
  for (unsigned i=0; i
    std::cout << ' ' << myvector[i];
  std::cout << '\n';
  return 0;
}
结果:
myvector contains: 4 5 7 8 9 10
5.6 clear函数
void clear();
清除vector中所有元素,然后vector的size大小变为0
5.6    swap 函数
void swap (vector& x);
作用就是交换两个vector中的元素。示例:
#include 
#include 
int main ()
{
  std::vector<</span>int> foo (3,100);   // three ints with a value of 100
  std::vector<</span>int> bar (5,200);   // five ints with a value of 200
  foo.swap(bar);
  std::cout << "foo contains:";
  for (unsigned i=0; i
    std::cout << ' ' << foo[i]<<endl;
  std::cout << "bar contains:";
  for (unsigned i=0; i
    std::cout << ' ' << bar[i]<<endl;
  return 0;
}
结果:
foo contains: 200 200 200 200 200 
bar contains: 100 100 100 

5.7      emplace 函数(C++11

template 
iterator emplace (const_iterator position, Args&&... args);

这也是一个插入函数,但不同的新元素是通过参数中的args构造的,这个和insert的有所不同。目前我是这么理解的。

 

#include 
#include 
int main ()
{
  std::vector<</span>int> myvector = {10,20,30};
  auto it = myvector.emplace ( myvector.begin()+1, 100 );
  myvector.emplace ( it, 200 );
  myvector.emplace ( myvector.end(), 300 );
  std::cout << "myvector contains:";
  for (auto& x: myvector)
    std::cout << ' ' << x;
  std::cout << '\n';
  return 0;
}

结果:

myvector contains: 10 200 100 20 30 300

5.8      emplace_back 函数

template 
void emplace_back (Args&&... args);

在函数的末尾构造并插入一个新元素,这个函数和push_back函数类似,不同的是push_back函数通过复制或者move元素来插入。示例:

#include 
#include 
int main ()
{
  std::vector<</span>int> myvector = {10,20,30};
  myvector.emplace_back (100);
  myvector.emplace_back (200);
  std::cout << "myvector contains:";
  for (auto& x: myvector)
    std::cout << ' ' << x;
  std::cout << '\n';
  return 0;
}

结果:

myvector contains: 10 20 30 100 200

6       关于分配器的函数

allocator_type get_allocator() const;

函数返回vector相关联的分配器对象的复制。示例:

#include 
#include 
int main ()
{
  std::vector<</span>int> myvector;
  int * p;
  unsigned int i;
  // allocate an array with space for 5 elements using vector's allocator:
  p = myvector.get_allocator().allocate(5);
  // construct values in-place on the array:
  for (i=0; i<5; i++) myvector.get_allocator().construct(&p[i],i);
  std::cout << "The allocated array contains:";
  for (i=0; i<5; i++) std::cout << ' ' << p[i];
  std::cout << '\n';
  // destroy and deallocate:
  for (i=0; i<5; i++) myvector.get_allocator().destroy(&p[i]);
  myvector.get_allocator().deallocate(p,5);
  return 0;
}

结果:

The allocated array contains: 0 1 2 3 4

   关于迭代器的函数

begin       Return iterator to beginning (public member function )

end          Return iterator to end (public member function )

rbegin     Return reverse iterator to reverse beginning (public member function )

rend                  Return reverse iterator to reverse end (public member function )

cbegin     Return const_iterator to beginning (public member function )

cend        Return const_iterator to end (public member function )

crbegin   Return const_reverse_iterator to reversebeginning (public member function )

crend      Return const_reverse_iterator to reverse end (public member function )

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值