[C++] std::vector


std::vector

向量是表示可以動態改變大小的數組的序列容器。
就像數組一樣,向量為它們的元素使用連續的存儲位置,這意味着它們的元素也可以使用對其元素的常規指針的偏移進行訪問,並且與數組中一樣有效。但是與數組不同的是,它們的大小可以動態地改變,其存儲由容器自動處理。
在內部,向量使用動態分配的數組來存儲它們的元素。這個數組可能需要重新分配,以便在插入新元素時增加大小,這意味着分配一個新數組並將所有元素移動到它。這在處理時間方面是一項相對昂貴的任務,因此,每次向容器添加元素時,向量不會重新分配。
相反,向量容器可以分配一些額外的存儲以適應可能的增長,並且因此容器可以具有大於容納其元素(即其大小)嚴格需要的存儲空間的實際容量。
庫可以實現不同的增長策略,以平衡內存使用和重新分配。但在任何情況下,重新分配只應該以對數增長的大小間隔發生,以便在向量的末端插入單個元素可以提供有平攤的恆定時間復雜度(見push_back)。
因此,與數組相比,向量消耗更多的內存,以便有效地管理存儲和動態增長的能力。
與其他動態序列容器(deques,lists和forward_lists)相比,向量非常有效地訪問其元素(就像數組),並且相對有效地從其結尾添加或刪除元素。
對於涉及在不同於其他位置的位置插入或刪除元素的操作,它們執行得比其他位置更差。

如果容器為空,則begin()和end()返回的是同一個迭代器,都是尾后迭代器

迭代器失效:改變vector對象容量的操作都會導致迭代器失效

迭代器不能相加。

迭代器相減的結果類型是difference::type,是一個有符號的數。

特性

有序

序列容器中的元素以嚴格的線性順序排列。單個元素按其順序通過其位置訪問。

動態數組

允許直接訪問序列中的任何元素,甚至通過指針算術,並在序列結尾提供相對快速的添加/刪除元素。

自動存儲

容器使用allocator對象動態處理其存儲需求。

vector (constructor)

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 <class InputIterator>
vector (InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type());
copy (4)
vector (const vector& x);
vector (const vector& x, const allocator_type& alloc);
move (5)
vector (vector&& x);
vector (vector&& x, const allocator_type& alloc);
initializer list (6)
vector (initializer_list<value_type> il,
const allocator_type& alloc = allocator_type());

代碼舉例

#include <iostream>
#include <vector>

int main() {
    std::vector<int> first; // default(1)
    std::vector<int> second(4, 100); // fill(2)
    std::vector<int> third(second.begin(), second.end()); // range(3)
    std::vector<int> fourth(third); // copy(4)

    // the iterator constructor can also be used to construct from arrays:
    int myints[] = {16,2,77,29};
    std::vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));

    std::cout << "The contents of fifth are:";
    for (std::vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';

    return 0;
}    
Output:
The contents of fifth are: 16 2 77 29

 

std::vector::operator=

將新內容分配給容器,替換其當前內容,並相應地修改其大小。
任何在容器中的元素被訪問前都會陪分配或銷毀。

#include <iostream>
#include <vector>

int main() {
    std::vector<int> foo(3, 0);
    std::vector<int> bar(5, 0);

    bar = foo;
    foo = std::vector<int>();

    std::cout << "Size of foo: " << int(foo.size()) << '\n';
    std::cout << "Size of var: " << int(bar.size()) << '\n';
    return 0;
}
Output:
Size of foo: 0
Size of bar: 3

 

std::vector::assign

將新內容分配給向量,替換其當前內容,並相應地修改其大小。
在調用之前,容器中保存的任何元素都被銷毀,並被新構造的元素替換(元素的賦值不發生)。
這將導致所分配的存儲空間的自動重新分配,當且僅當新的向量大小超過當前的向量容量。

// vector assign
#include <iostream>
#include <vector>

int main () {
    std::vector<int> first;
    std::vector<int> second;
    std::vector<int> third;

    first.assign(7, 100); // 7 ints with a value of 100

    std::vector<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;
}
Output:
Size of first: 7
Size of second: 5
Size of third: 3

 

operator= 與 assign 區別

相同點:operator=與assign都是釋放原來的內存空間,並分配新的內存空間

不同點:assign返回值為none  operator=返回值為*this

 

Vector Iterators

begin()  Return iterator to beginning

end()     Return iterator to end

rbegin()    Return reverse iterator to reverse beginning

rend()    Return reverse iterator to reverse end

cbegin()   Return const_iterator to beginning

cend()    Return const_iterator to end

crbegin()   Return const_reverse_iterator to reverse beginning

crend()   Return const_reverse_iterator to reverse end

 

std::vector::cbegin/cend

返回指向容器中首元素的迭代器

返回指向容器中尾元素下一個元素的迭代器

返回的const_iterator所指的對象值不能改變。

// vector::cbegin/cend
#include <iostream>
#include <vector>

int main () {
    std::vector<int> myvector = {10, 20, 30, 40, 50};

    std::cout << "myvector contains:";

    for (auto it = myvector.cbegin(); it != myvector.cend(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';

    return 0;
}
Output:
myvector contains: 10 20 30 40 50

 

std::vector::size    Return size

std::vector::capacity  Return size of allocated storage capacity

std::vector::max_size   Return maximum size

// comparing size, capacity and max_size
#include <iostream>
#include <vector>

int main ()
{
    std::vector<int> myvector;

    // set some content in the vector:
    for (int i=0; i < 100; i++) 
     myvector.push_back(i);
std::cout
<< "size: " << myvector.size() << "\n"; std::cout << "capacity: " << myvector.capacity() << "\n"; std::cout << "max_size: " << myvector.max_size() << "\n"; return 0; }
A possible output for this program could be:
size: 100
capacity: 128
max_size: 1073741823

size 返回實際容量

capacity 返回默認容量

max_size 返回向量可以容納的最大元素數,這個max_size由系統或庫限制。但容器絕對不能保證能夠達到該尺寸,因為在達到該大小之前的任何時間點仍然無法分配存儲空間。

std::vector::empty  Test whether vector is empty

std::vector::operator[]  

Return a reference to the element at position n in the vector container.

// vector::operator[]
#include <iostream>
#include <vector>

int main ()
{
    std::vector<int> myvector (10);   // 10 zero-initialized elements

    std::vector<int>::size_type sz = myvector.size();

    // assign some values:
    for (unsigned i = 0; i < sz; i++) 
     myvector[i] = i; // reverse vector using operator[]: for (unsigned i = 0; i < sz / 2; i++) { int temp; temp = myvector[sz - 1 - i]; myvector[sz - 1 - i] = myvector[i]; myvector[i] = temp; } std::cout << "myvector contains:"; for (unsigned i = 0; i < sz; i++) std::cout << ' ' << myvector[i]; std::cout << '\n'; return 0; }
Output:
myvector contains: 9 8 7 6 5 4 3 2 1 0

 

std::vector::at       Access element

std::vector::front  Access first element

std::vector::back  Access last element.

 

std::vector::data   Access data

Returns a direct pointer to the memory array used internally by the vector to store its owned elements.

// vector::data
#include <iostream>
#include <vector>

int main() {
    std::vector<int> myvector(5);

    int* p = myvector.data();

    *p = 10;
    ++p;
    *p = 20;
    p[2] = 100;

    std::cout << "myvector contains:";
    for (unsigned i = 0; i < myvector.size(); ++i)
        std::cout << ' ' << myvector[i];
    std::cout << '\n';

    return 0;
}
myvector contains: 10 20 0 100 0

 

std::vector::push_back  Add element at the end

std::vector::pop_back    Delete last element

std::vector::insert      Insert elements

通過在指定位置的元素之前插入新元素來擴展向量,通過插入的元素數量有效地增加容器大小。

這將導致所分配的存儲空間的自動重新分配,當且僅當新的向量大小超過當前的向量容量。

由於向量使用數組作為其底層存儲,因此將元素插入到向量端以外的位置會導致容器將位置之后的所有元素重新定位到新位置。與通過其他類型的序列容器(例如list或forward_list)執行相同操作的操作相比,這通常是一個低效的操作。

// inserting into a vector
#include <iostream>
#include <vector>

int main() {
    std::vector<int> myvector(3, 100);
    std::vector<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<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 < myvector.end(); it++)
        std::cout << ' ' << *it;
    std::cout << '\n';
    
    return 0;
}
Output:
myvector contains: 501 502 503 300 300 400 400 200 100 100 100

 

std::vector::erase      Erase elements

Removes from the vector either a single element (position) or a range of elements ([first,last)).

// erasing from vector
#include <iostream>
#include <vector>

int main ()
{
    std::vector<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 < myvector.size(); ++i)
        std::cout << ' ' << myvector[i];
    std::cout << '\n';

    return 0;
}
Output:
myvector contains: 4 5 7 8 9 10

 

std::vector::swap       Swap content

swap vector

// swap vectors
#include <iostream>
#include <vector>

int main ()
{
    std::vector<int> foo (3,100);   // three ints with a value of 100
    std::vector<int> bar (5,200);   // five ints with a value of 200

    foo.swap(bar);

    std::cout << "foo contains:";
    for (unsigned i=0; i<foo.size(); i++)
        std::cout << ' ' << foo[i];
    std::cout << '\n';

    std::cout << "bar contains:";
    for (unsigned i=0; i<bar.size(); i++)
        std::cout << ' ' << bar[i];
    std::cout << '\n';

    return 0;
}
Output:
foo contains: 200 200 200 200 200 
bar contains: 100 100 100 

 

std::vector::clear        Clear content

clearing vectors

// clearing vectors
#include <iostream>
#include <vector>

int main ()
{
    std::vector<int> myvector;
    myvector.push_back (100);
    myvector.push_back (200);
    myvector.push_back (300);

    std::cout << "myvector contains:";
    for (unsigned i=0; i<myvector.size(); i++)
        std::cout << ' ' << myvector[i];
    std::cout << '\n';

    myvector.clear();
    myvector.push_back (1101);
    myvector.push_back (2202);

    std::cout << "myvector contains:";
    for (unsigned i=0; i<myvector.size(); i++)
        std::cout << ' ' << myvector[i];
    std::cout << '\n';

    return 0;
}
Output:
myvector contains: 100 200 300
myvector contains: 1101 2202

 

std::vector::emplace        Construct and insert element

構建並添加元素

返回值指向新放置元素的迭代器。

通過在位置插入一個新元素來擴展容器。這個新元素是使用args作為構造的參數來構建的。

這有效地將容器尺寸增加了一個。

分配的存儲空間的自動重新分配發生,當且僅當新的向量大小超過當前的向量容量。

由於向量使用數組作為其底層存儲,因此將元素插入到向量端以外的位置會導致容器將所有位置之后的元素移位到新的位置。與其他類型的序列容器(例如list或forward_list)執行的操作相比,這通常是一個低效的操作。對於直接在最后擴展容器的成員函數,請參閱emplace_back。

如果重新分配發生,則與此容器相關的所有迭代器,指針和引用都將失效。

// vector::emplace
#include <iostream>
#include <vector>

int main ()
{
    std::vector<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;
}
Output:
myvector contains: 10 200 100 20 30 300

 

std::vector::emplace_back Construct and insert element at the end 

在向量的末尾插入一個新的元素,就在其最后一個元素之后。這個新元素是使用args作為構造函數的參數構建的。

這有效地將容器大小增加1,這導致所分配的存儲空間的自動重新分配,當僅當新的向量大小超過當前向量容量時。  

// vector::emplace_back
#include <iostream>
#include <vector>

int main ()
{
    std::vector<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;
}
Output:
myvector contains: 10 20 30 100 200

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM