array<T,N> : 一个有 N 个 T 类型元素的固定序列。除了需要指定元素的类型和个数之外,和常规数组没有太大的差别。显然,不能增加或删除元素。
1.初始化
#include <array>
#include <iostream>
using namespace std;
int main()
{
std::array<double,100> data;
std::array<double, 100> data1 {};
std::array<double, 10> values {0.5, 1.0, 1.5, 2.0};
//通过调用数组对象的成员函数 fill(),可以将所有元素设成给定值
values.fill(3.1415926);
//不检查越界
values[4] = values[3] + 2.O*values[1];
//检查越界
values.at (4) = values.at(3) + 2.O*values.at(1);
double total {};
for(auto&& value : values)
total += value;
std::array<std::string, 5> words {"one","two","three”,"four","five" };
std::cout << std::get<3>(words) << std::endl; // Output words[3]
std::cout << std::get<6>(words) << std::endl; // Compiler error message!
return 0;
}
2.访问元素
#include <iostream> // For standard streams
#include <iomanip> // For stream manipulators
#include <array> // For array<T,N>
int main()
{
const unsigned int min_wt {100U};
const unsigned int max_wt {250U};
const unsigned int wt_step {10U};
const size_t wt_count {1 + (max_wt - min_wt) / wt_step};
const unsigned int min_ht {48U};
const unsigned int max_ht {84U};
const unsigned int ht_step {2U};
const size_t ht_count { 1 + (max_ht - min_ht) / ht_step };
const double lbs_per_kg {2.20462};
const double ins_per_m {39.3701};
std::array<unsigned int, wt_count> weight_lbs;
std::array<unsigned int, ht_count> height_ins;
// Create weights from lOOlbs in steps of lOlbs
for (size_t i{}, w{min_wt} ; i < wt_count ; w += wt_step, ++i)
{
weight_lbs.at(i) = w;
}
//Create heights from 48 inches in steps of 2 inches
unsigned int h{min_ht};
for(auto& height : height_ins)
{
height = h;
h += ht_step;
}
//Output table headings
std::cout << std:: setw (7) <<" |";
for (const auto& w : weight_lbs)
std::cout << std:: setw (5) << w<<"11";
std::cout << std::endl;
// Output line below headings
for (size_t i{1} ; i < wt_count ; ++i)
std::cout<<"---------";
std::cout << std::endl;
double bmi {};
unsigned int feet {};
unsigned int inches {};
const unsigned int inches_per_foot {12U};
for (const auto& h : height_ins)
{
feet = h / inches_per_foot;
inches = h % inches_per_foot;
std::cout << std::setw (2) <<feet <<"'"<<std::setw (2) << inches <<"\""<<"|";
std::cout << std::fixed <<std::setprecision(1);
for (const auto& w : weight_lbs)
{
bmi = h / ins_per_m;
bmi = (w / lbs_per_kg) / (bmi*bmi);
std::cout << std:: setw (2) <<""<<bmi <<" |";
}
std::cout << std::endl;
}
for (size_t i {1} ; i < wt_count ; ++i)
std::cout << "---------";
std::cout << "\nBMI from 18.5 to 24.9 is normal" << std::endl;
}
3.迭代器
#include <iostream> // For standard streams
#include <iomanip> // For stream manipulators
#include <array> // For array<T,N>
#include <algorithm>//geberate
#include <numeric>//itoa
using namespace std;
int main()
{
array<double,5> height_ins{1,2,3,4,5};
unsigned int h {100U};
int ht_step=1,min_ht=0;
auto first = height_ins.begin();
auto last = height_ins.end () ;
while (first != last)
{
*first++=h;
h += ht_step;
}
//全局访问
// auto first = std::begin(height_ins);
// auto last = std::end (height_ins);
//lamba
unsigned int height {};
std::generate(std::begin(height_ins), std::end(height_ins),
[height, &min_ht, &ht_step]()mutable{ return height += height == 0 ? min_ht : ht_step; });
std::array<double, 10> values;
std::iota(std::begin(values), std::end(values),10.0);
//全局函数或成员函数 rbegin() 和 rend() 可以分别得到指向最一个元素和第一个元素前一个位置的反向迭代器。
//函数 crbegin() 和 crend() 可以返回 const 反向迭代器。
std::array<double, 5> these {1.0, 2.0, 3.0, 4.0, 5.0};
double sum {};
auto start = these.rbegin();
auto finish = these.rend();
while(start != finish)
sum += *(start++);
std::cout << "The sum of elements in reverse order is " << sum << std::endl;
return 0;
}
4.比较大小
//元素比较
//对 ==,如果两个数组对应的元素都相等,会返回 true。对于 !=,两个数组中只要有一个元素不相等,就会返回 true
std::array<double,4> these {1.0, 2.0, 3.0, 4.0};
std::array<double,4> those {1.0, 2.0, 3.0, 4.0};
std::array<double,4> them {1.0, 3.0, 3.0, 2.0};
if (these == those) std::cout << "these and those are equal." << std::endl;
if (those != them) std::cout << "those and them are not equal."<< std::endl;
if (those < them) std::cout << "those are less than them."<< std::endl;
if (them > those) std::cout << "them are greater than those." << std::endl;
vector<T> : 包含 T 类型元素的序列容器,容器的大小可以自动增长,从而可以包含任意数量的元素。
1.初始化
#include <vector>
#include <iostream>
using namespace std;
#include <array> // For array<T,N>
int main()
{
std::vector<double> values;
values.reserve(20);//这样就设置了容器的内存分配,至少可以容纳 20 个元素。
std::vector<unsigned int> primes {2u, 3u, 5u, 7u, 11u, 13u, 17u, 19u};
std::vector<double> values(20);//使用初始元素个数来生成 vector 容器:
std::vector<double> values {20};//vector 并没有 20 个元素。它只有一个元素,并以 20 作为初始值。
//添加元素会导致分配额外的内存。
//第二个参数指定了所有元素的初始值,因此这 20 个元素的值都是 99L。
//第一个元素指定了 vector 中的元素个数
std::vector<long> numbers(20, 99L);
//可以用元素类印相同的容器来初始化 vector<T> 容器。用一对迭代器来指定初始值的范围。
std::array<std :: string, 5> words {"one", "two","three", "four", "five"};
std::vector<std::string> words_copy {std::begin(words) , std::end(words)};
std::vector<std::string〉 words_copy {std::make_move_iterator
(std::begin(words)),std::make_move_iterator(std:: end(words))};
}
2.容量大小
//vector 的容量大小,是指在不分配更多内存的情况下可以保存的最多元素个数,
//这时 可能有 20 个元素,也可能没有。
//vector 的大小是它实际所包含的元素个数,也就是有值的元素的个数
std::vector<size_t> primes { 2, 3, 5, 7, 11, 13, 17, 19, 23,
29, 31, 37, 41 ,43 ,47 };
std::cout << "The size is " << primes.size() << std::endl;
std::cout << "The capacity is" << primes.capacity() << std::endl;
//输出语句输出的容器大小和容董都为 15,这是由初始化列表决定的。然而,如果用 push_back() 函数添加一个元素,
//然后再输出容器的大小和容量,这时大小变为 16,容量变为 30。
auto nElements = primes.size();
for(auto& prime : primes)
prime *= 2;
//第一个 resize() 调用会把元素的个数变为参数指定的值,所以会增加两个用默认值初始化的元素。如果添加了一个元素,导致超过当前容器的容景,容量会自动增加。
//第二个 resize() 调用将元素增加到第一个参数指定的个数,并用第二个参数初始化增加的新元素。
//第三个 resize() 凋用将容器大小设为 6,小于当前元素的个数。当需要减小容器的大小时,会移除多余的元素,这就好像重复调用了几次 pop_back() 函数。
std::vector<int> values {1,2,3};
values.resize (5);
values.resize (7, 99);
values.resize (6);
3.插入元素
//emplace() 的第一个参数是一个迭代器,它确定了对象生成的位置。
//对象会被插入到迭代器所指定元素的后面。第一个参数后的参数,都作为插入元素的构造函数的参数传入。
std::vector<std::string> words {"first", "second"};
// Inserts string(5,'A') as 2nd element
auto iter = words.emplace(++std::begin(words),5,'A');
//Inserts string ("$$$$") as 3rd element
words.emplace(++iter, "$$$$");
//成员函数 insert() 可以在 vector 中插入一个或多个元素。第一个参数总是一个指向插入点的 const 或 non-const 迭代器。
//元素会被迅速插入到第一个参数所指向元素的前面,如果第一个参数是一个反向迭代器,元素会被插入到迭代器所指向元素的后面。
std::vector<std::string> words { "one","three","eight"} //Vector with 3 elements
auto iter = words.insert(++std::begin(words), "two");//"one" "two" "three" "eight"
std:: string more[] {"five", "six", "seven" }; // Array elements to be inserted
iter = words.insert(--std::end(words) , std::begin(more), std::end(more));//"one" "two" "three" "five" "six" "seven" "eight"
iter = words.insert(std::end(words), "ten");//"one" "two" "three" "five" "six" "seven" "eight" "ten"
iter = words.insert(std::cend(words)-1, 2, "nine");//"one" "two" "three" "five" "six" "seven" "eight" "nine" "nine" "ten"
iter = words.insert(std::end(words), {std::string {"twelve"},std::string {"thirteen"}});
//"one" "two" "three" "five" "six" "seven" "eight" "nine" "nine" "ten" "twelve" "thirteen"
//find() 算法会在头两个参数所指定的一段元素中,搜索第三个参数指定的元素,返回第一个找到的元素,因此会找到 String("one")。
std::vector<std::string> str { "one", "two", "one", "three"};
auto riter = std::find(std::rbegin(str), std::rend(str) , "one");
str.insert(riter.base(), "five");//"one", "two", "one", "five", "three"
4.迭代器
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include<iterator>
using std::string;
using std::vector;
using namespace std;
int main()
{
vector<string> words; // Stores words to be sorted
words.reserve(10); // Allocate some space for elements
std::cout << "Enter words separated by spaces. Enter Ctrl+Z on a separate line to end:" << std::endl;
std::copy(std::istream_iterator <string> {std::cin},
std::istream_iterator <string> {},std::back_inserter(words));
std::cout << "Starting sort." << std::endl;
bool out_of_order {false};
while (true)
{
for (auto first = words.begin() + 1; first != words.end(); ++first)
{
if (*(first - 1) > *first)
{ // Out of order so swap them
std::swap(*first, *(first - 1));
out_of_order = true;
}
}
if (!out_of_order) // If they are in order (no swaps necessary)...
break; // ...we are done...
out_of_order = false; // ...otherwise, go round again.
}
std::cout << "your words in ascending sequence:" << std::endl;
std::copy(std::begin(words), std::end(words), std::ostream_iterator < string > {std::cout, " "});
std::cout << std::endl;
// Create a new vector by moving elements from words vector
vector<string> words_copy {std::make_move_iterator(std::begin(words)),std::make_move_iterator(std::end(words))};
std::cout << "\nAfter moving elements from words, words_copy contains:" << std::endl;
std::copy(std::begin(words_copy), std::end(words_copy), std::ostream_iterator < string > {std::cout, " "});
std::cout << std::endl;
// See what's happened to elements in words vector...
std::cout << "\nwords vector has " << words.size() << " elements\n";
if (words.front().empty())
std::cout << "First element is empty string object." << std::endl;
std::cout << "First element is \"" << words.front() << "\"" << std::endl;
}
5.访问元素
std::vector<double> values (20);
values[0] = 3.14159;
values[1] = 5.0;
values[2] = 2.0*values[0]*values[1];
//vector 的成员函数 front() 和 back() 分別返回序列中第一个和最后一个元素的引用,
std::cout << values.front () << std::endl; // Outputs 3.14159
//成员函数 data() 返回一个指向数组的指针,它在内部被用来存储元素
//pData 是 double* 类型,一般来说,data() 返回 vector<T> 容器的 T* 类型的值。
auto pData = values.data();
6.删除元素
std::vector<int> data(100, 99);// Contains 100 elements initialized to 99
data.clear(); // Remove all elements 所以容量还是 100。
std::vector<int> data(100, 99); // Contains 100 elements initialized to 99
data.pop_back(); // Remove the last element
//假设要删除 data 中的第二个元素
std::swap(std::begin(data)+1,std::end(data)-1);
data.pop_back();
// Interchange 2nd element with the last data.pop_back(); // Remove the last element
//如果要去掉容器中多余的容量,例如不再向容器中添加新元素,那么可以通过使用成 员函数 shrink_to_fit() 来实现:
data.shrink_to_fit(); // Reduce the capacity to that needed for elements
auto iter = data.erase(std::begin(data)+1); //Delete the second element它指向被删除元素后的一个元素
// Delete the 2nd and 3rd elements
auto iter = data.erase(std::begin(data)+1,std::begin(data)+3);//第二个迭代器指向这段元素末尾的下一个位置
//如果在 remove() 操作后输出 words 中的元素,只会输出前 5 个元素。尽管 size() 返回的值仍然是 7,
//而且最后两个元素仍然存在,但是它们被替换成了空字符串对象。
std::vector<std::string> words { "one", "none","some", "all”, "none", "most","many"};
auto iter = std::remove(std::begin(words), std::end(words), "none");
words.erase(iter, std::end(words));//Remove surplus elements
erase-remove,执行删除操作后,iter 指向最后一个元素之后的位置,
所以它标识了被删除序列的第一个元素,被删除序列的结束位置由 std::end(words) 指定
words.erase(std::remove(std::begin(words), std::end(words),"none"), std::end(words));
// Understanding how capacity is increased in a vector container
#include <iostream> // For standard streams
#include <vector> // For vector container
int main()
{
std::vector <size_t> sizes; // Record numbers of elements
std::vector <size_t> capacities; // and corresponding capacities
size_t el_incr {10}; // Increment to initial element count
size_t incr_count {4 * el_incr}; // Number of increments to element count
for (size_t n_elements {}; n_elements < incr_count; n_elements += el_incr)
{
std::vector<int> values(n_elements);
std::cout << "\nAppending to a vector with " << n_elements << " initial elements:\n";
sizes.push_back(values.size());
size_t space {values.capacity()};
capacities.push_back(space);
// Append elements to obtain capacity increases
size_t count {}; // Counts capacity increases
size_t n_increases {10};
while (count < n_increases)
{
values.push_back(22); // Append a new element
if (space < values.capacity()) // Capacity increased...
{ // ...so record size and capacity
space = values.capacity();
capacities.push_back(space);
sizes.push_back(values.size());
++count;
}
}
// Show sizes & capacities when increments occur
std::cout << "Size/Capacity: ";
for (size_t i {}; i < sizes.size(); ++i)
std::cout << sizes.at(i) << "/" << capacities.at(i) << " ";
std::cout << std::endl;
sizes.clear(); // Remove all elements
capacities.clear(); // Remove all elements
}
}
7.增加元素
std::vector<double> values;
values.push_back(3.1415926);
std::vector<std::string> words;
words.push_back(string("adiabatic"));
/ Move string("adiabatic") into the vector
words.push_back ("adiabaticft"); // Move string("adiabatic")
// emplace back() 比 push_back() 更有效率
std::vector<std::string> words;
words.push_back (std:: string ("facetious") ) ; // Calls string constructor & moves the string object
words•emplace_back("abstemious");// Calls string constructor to create element in place
// emplace_back() 函数会调用接收三个参数的 string 构造函数,生成 string 对象,
// 然后把它添加到 words 序列中。构造函数会生成一个从索引 2 幵始、包含 str 中三个字符的子串。
std::string str {"alleged"};
words.emplace_back(str, 2, 3);
// Create string object corresponding to "leg" in place