C++11中std::array的使用
来源:互联网 发布:电商发展数据统计 编辑:程序博客网 时间:2024/06/05 20:48
std::array是在C++11中才引入的,与内置数组相比,array是一种更安全、更容易使用的数组类型。与内置数组类似,array对象的大小是固定的。因此,array不支持添加和删除元素以及改变容器大小的操作。与内置数组一样,标准库array的大小也是类型的一部分。当定义一个array时,除了指定元素类型,还要指定容器大小。为了使用array类型,我们必须同时指定元素类型和大小。array仅仅是为普通数组添加了一些成员或全局函数,这使得数组能够被当成标准容器来使用。array不能被动态地扩展或压缩。
由于大小是array类型的一部分,array不支持普通的容器构造函数。array大小固定的特性也影响了它所定义的构造函数的行为。与其它容器不同,一个默认构造的array是非空的:它包含了与其大小一样多的元素。这些元素都被默认初始化,就像一个内置数组中的元素那样。如果我们对array进行列表初始化,初始值的数目必须等于或小于array的大小。如果初始值数目小于array的大小,则它们被用来初始化array中靠前的元素,所有剩余元素都会进行值初始化。在这两种情况下,如果元素类型是一个类类型,那么该类必须有一个默认构造函数,以使值初始化能够进行。
值得注意的是,虽然我们不能对内置数组类型进行拷贝或对象赋值操作,但array并无此限制。与其它容器一样,array也要求初始值的类型必须与要创建的容器类型相同。此外,array还要求元素类型和大小也都一样,因为大小是array类型的一部分。大小为0的array容器是允许的,但是这样的数组里的元素是不能被解引用的(dereferenced)。array是一个简单集合,故支持相应的初始化aggregate-initialization。一个数组同时也可以当作一个有N个相同类型元素的tuple(多元组)。
Arrays are fixed-size sequence containers: they hold a specific number of elements ordered in a strict linear sequence. Just like the native implementation of fixed arrays, the length of a std::array must be set at compile time.
一个容器就是一些特定类型对象的集合。顺序容器(sequential container)为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖于元素的值,而是与元素加入容器时的位置相对应。
标准库中的顺序容器包括:
(1)、vector:可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢。
(2)、deque:双端队列。支持快速随机访问。在头尾位置插入/删除速度很快。
(3)、list:双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除操作速度都很快。
(4)、forward_list:单向链表。只支持单向顺序访问。在链表任何位置进行插入/删除操作速度都很快。
(5)、array:固定大小数组。支持快速随机访问。不能添加或删除元素。
(6)、string:与vector相似的容器,但专门用于保存字符。随机访问快。在尾部插入/删除速度快。
除了固定大小的array外,其它容器都提供高效、灵活的内存管理。我们可以添加和删除元素,扩张和收缩容器的大小。容器保存元素的策略对容器操作的效率有着固定的,有时是重大的影响。在某些情况下,存储策略还会影响特定容器是否支持特定操作。
例如,string和vector将元素保存在连续的内存空间中。由于元素是连续存储的,由元素的下标来计算其地址是非常快速的。但是,在这两种容器的中间位置添加或删除元素就会非常耗时:在一次插入或删除操作后,需要移动插入/删除位置之后的所有元素,来保持连续存储。而且,添加一个元素有时可能还需要分配额外的存储空间。在这种情况下,每个元素都必须移动到新的存储空间中。
list和forward_list两个容器的设计目的是令容器任何位置的添加和删除操作都很快速。作为代价,这两个容器不支持元素的随机访问:为了访问一个元素,我们只能遍历整个容器。而且,与vector、deque和array相比,这两个容器的额外内存开销也很大。
deque是一个更为复杂的数据结构。与string和vector类似,deque支持快速的随机访问。与string和vector一样,在deque的中间位置添加或删除元素的代价(可能)很高。但是,在deque的两端添加或删除元素都是很快的,与list或forward_list添加删除元素的速度相当。
forward_list和array是新C++标准增加的类型。与内置数组相比,array是一个种更安全、更容易使用的数组类型。与内置数组类似,array对象的大小是固定的。因此,array不支持添加和删除元素以及改变容器大小的操作。forward_list的设计目标是达到与最好的手写的单向链表数据结构相当的性能。因此,forward_list没有size操作,因为保存或计算其大小就会比手写链表多出额外的开销。对其他容器而言,size保证是一个快速的常量时间的操作。
通常,使用vector是最好的选择,除法你有很好的理由选择其他容器。
以下是一些选择容器的基本原则:
(1)、除法你有很好的理由选择其他容器,否则应该使用vector;
(2)、如果你的程序有很多小的元素,且空间的额外开销很重要,则不要使用list或forward_list;
(3)、如果程序要求随机访问元素,应使用vector或deque;
(4)、如果程序要求在容器的中间插入或删除元素,应使用list或forward_list;
(5)、如果程序需要在头尾位置插入或删除元素,但不会在中间位置进行插入或删除操作,则使用deque;
(6)、如果程序只有在读取输入时才需要在容器中间位置插入元素,随后需要随机访问元素,则:首先,确定是否真的需要在容器中间位置添加元素。当处理输入数据时,通常可以很容器地向vector追加数据,然后再调用标准库的sort函数来重排容器中的元素,从而避免在中间位置添加元素。如果必须在中间位置插入元素,考虑在输入阶段使用list,一旦输入完成,将list中的内容拷贝到一个vector中。
如果你不确定应该使用哪种容器,那么可以在程序中只使用vector和list公共的操作:使用迭代器,不使用下标操作,避免随机访问。这样,在必要时选择使用vector或list都很方便。
一般来说,每个容器都定义在一个头文件中,文件名与类型名相同。即,deque定义在头文件deque中,list定义在头文件list中,以此类推。容器均定义为模板类。
顺序容器几乎可以保存任意类型的元素。特别是,我们可以定义一个容器,其元素的类型是另一个容器。这种容器的定义与任何其他容器类型完全一样:在尖括号中指定元素类型(此种情况下,是另一种容器类型)。
除了顺序容器外,标准库还定义了三个顺序容器适配器:stack、queue和priority_queue。适配器(adaptor)是标准库中的一个通用概念。容器、迭代器和函数都有适配器。本质上,一个适配器是一种机制,能使某种事物的行为看起来像另外一种事物一样。一个容器适配器接受一种已有的容器类型,使其行为看起来像一种不同的类型。下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:
#include "array.hpp"#include <iostream>#include <array>#include <tuple>#include <string>///////////////////////////////////////////////////////// https://msdn.microsoft.com/en-us/library/bb983093.aspxint test_array_3(){// array::assign: Replaces all elementstypedef std::array<int, 4> Myarray;Myarray c0 = { 0, 1, 2, 3 };// display contents " 0 1 2 3" for (Myarray::const_iterator it = c0.begin();it != c0.end(); ++it)std::cout << " " << *it;std::cout << std::endl;Myarray c1;c1.assign(4);// display contents " 4 4 4 4" for (Myarray::const_iterator it = c1.begin();it != c1.end(); ++it)std::cout << " " << *it; // 4 4 4 4std::cout << std::endl;return 0;}/////////////////////////////////////////////////////////// reference: http://en.cppreference.com/w/cpp/container/arrayint test_array_2(){// construction uses aggregate initializationstd::array<int, 3> a1{ { 1, 2, 3 } }; // double-braces required in C++11 (not in C++14)std::array<int, 3> a2 = { 1, 2, 3 }; // never required after =std::array<std::string, 2> a3 = { std::string("a"), "b" };// container operations are supportedstd::sort(a1.begin(), a1.end());std::reverse_copy(a2.begin(), a2.end(), std::ostream_iterator<int>(std::cout, " "));std::cout << '\n';// ranged for loop is supportedfor (const auto& s : a3)std::cout << s << ' ';std::cout << '\n';return 0;}//////////////////////////////////////////////////////////// reference: http://www.cplusplus.com/reference/array/array/// default initialization (non-local = static storage):std::array<int, 3> global; // zero-initialized: {0,0,0}int test_array_1(){{ // array::array: The array classes are aggregate types, and thus have no custom constructors. // default initialization (local = automatic storage):std::array<int, 3> first; // uninitialized: {?,?,?}// initializer-list initializations:std::array<int, 3> second = { 10, 20 }; // initialized as: {10,20,0}std::array<int, 3> third = { 1, 2, 3 }; // initialized as: {1,2,3}// copy initialization:std::array<int, 3> fourth = third; // copy: {1,2,3}std::cout << "The contents of fourth are:";for (auto x : fourth) std::cout << ' ' << x;std::cout << '\n';}{ // array::at: Returns a reference to the element at position n in the arraystd::array<int, 10> myarray;// assign some values:for (int i = 0; i < 10; i++) myarray.at(i) = i + 1;// print content:std::cout << "myarray contains:";for (int i = 0; i < 10; i++)std::cout << ' ' << myarray.at(i);std::cout << '\n';}{ // array::back: Returns a reference to the last element in the array container. // array::front: Returns a reference to the first element in the array container.std::array<int, 3> myarray = { 5, 19, 77 };std::cout << "front is: " << myarray.front() << std::endl; // 5std::cout << "back is: " << myarray.back() << std::endl; // 77myarray.back() = 50;myarray.front() = 999;std::cout << "myarray now contains:";for (int& x : myarray) std::cout << ' ' << x; // 999 19 50std::cout << '\n';}{ // array::begin: Returns an iterator pointing to the first element in the array container. // array::end: Returns an iterator pointing to the past-the-end element in the array container.std::array<int, 5> myarray = { 2, 16, 77, 34, 50 };std::cout << "myarray contains:";for (auto it = myarray.begin(); it != myarray.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';}{ // array::cbegin: Returns a const_iterator pointing to the first element in the array container. // array::cend: Returns a const_iterator pointing to the past-the-end element in the array container.std::array<int, 5> myarray = { 2, 16, 77, 34, 50 };std::cout << "myarray contains:";for (auto it = myarray.cbegin(); it != myarray.cend(); ++it)std::cout << ' ' << *it; // cannot modify *itstd::cout << '\n';}{ // array::crbegin: Returns a const_reverse_iterator pointing to the last element in the array container. // array::crend: Returns a const_reverse_iterator pointing to the theoretical element preceding // the first element in the vector, which is considered its reverse end.std::array<int, 6> myarray = { 10, 20, 30, 40, 50, 60 };std::cout << "myarray backwards:";for (auto rit = myarray.crbegin(); rit < myarray.crend(); ++rit)std::cout << ' ' << *rit; // cannot modify *ritstd::cout << '\n';}{ // array::data: Returns a pointer to the first element in the array object.const char* cstr = "Test string";std::array<char, 12> charray;std::memcpy(charray.data(), cstr, 12);std::cout << charray.data() << '\n';}{ // array::empty: Returns a bool value indicating whether the array container is empty, i.e. whether its size is 0.std::array<int, 0> first;std::array<int, 5> second;std::cout << "first " << (first.empty() ? "is empty" : "is not empty") << '\n';std::cout << "second " << (second.empty() ? "is empty" : "is not empty") << '\n';}{ // array::fill: Sets val as the value for all the elements in the array object.std::array<int, 6> myarray;myarray.fill(5);std::cout << "myarray contains:";for (int& x : myarray) { std::cout << ' ' << x; }std::cout << '\n';}{ // array::max_size: Returns the maximum number of elements that the array container can hold // array::size: Returns the number of elements in the array container.std::array<int, 10> myints;std::cout << "size of myints: " << myints.size() << '\n';std::cout << "max_size of myints: " << myints.max_size() << '\n';std::cout << "sizeof(myints): " << sizeof(myints) << std::endl;}{ // array::operator[]: Returns a reference to the element at position n in the array container.std::array<int, 10> myarray;unsigned int i;// assign some values:for (i = 0; i < 10; i++) myarray[i] = i;// print contentstd::cout << "myarray contains:";for (i = 0; i < 10; i++)std::cout << ' ' << myarray[i];std::cout << '\n';}{ // array::rbegin: Returns a reverse iterator pointing to the last element in the array container. // array::rend: Returns a reverse iterator pointing to the theoretical element preceding // the first element in the array (which is considered its reverse end).std::array<int, 4> myarray = { 4, 26, 80, 14 };std::cout << "myarray contains:";for (auto rit = myarray.rbegin(); rit < myarray.rend(); ++rit)std::cout << ' ' << *rit;std::cout << '\n';}{ // array::swap: Exchanges the content of the array by the content of x, // which is another array object of the same type (including the same size).std::array<int, 5> first = { 10, 20, 30, 40, 50 };std::array<int, 5> second = { 11, 22, 33, 44, 55 };first.swap(second);std::cout << "first:";for (int& x : first) std::cout << ' ' << x;std::cout << '\n';std::cout << "second:";for (int& x : second) std::cout << ' ' << x;std::cout << '\n';}{ // std::get: Returns a reference to the Ith element of array arr // std::tuple_element<array>: Accesses the static type of the elements in an array object as if it was a tuple.std::array<int, 3> myarray = { 10, 20, 30 };std::tuple<int, int, int> mytuple(10, 20, 30);std::tuple_element<0, decltype(myarray)>::type myelement; // int myelementmyelement = std::get<2>(myarray);std::get<2>(myarray) = std::get<0>(myarray);std::get<0>(myarray) = myelement;std::cout << "first element in myarray: " << std::get<0>(myarray) << "\n";std::cout << "first element in mytuple: " << std::get<0>(mytuple) << "\n";}{ // std::relational operators(array): Performs the appropriate comparison operation between the array containers lhs and rhs.std::array<int, 5> a = { 10, 20, 30, 40, 50 };std::array<int, 5> b = { 10, 20, 30, 40, 50 };std::array<int, 5> c = { 50, 40, 30, 20, 10 };if (a == b) std::cout << "a and b are equal\n";if (b != c) std::cout << "b and c are not equal\n";if (b<c) std::cout << "b is less than c\n";if (c>b) std::cout << "c is greater than b\n";if (a <= b) std::cout << "a is less than or equal to b\n";if (a >= b) std::cout << "a is greater than or equal to b\n";}return 0;}
GitHub:https://github.com/fengbingchun/Messy_Test
- C++11中std::array的使用
- C++/C++11中std::transform的使用
- C++/C++11中std::queue的使用
- C++/C++11中std::priority_queue的使用
- C++/C++11中std::deque的使用
- C++/C++11中std::stack的使用
- C++/C++11中std::numeric_limits的使用
- C++/C++11中std::exception的使用
- C++/C++11中std::runtime_error的使用
- C++11中std::unordered_map的使用
- C++11中std::move的使用
- C++11中std::function的使用
- C++11中std::forward的使用
- C++11中std::bind的使用
- C++11中std::addressof的使用
- C++11中std::tuple的使用
- C++11中std::mutex的使用
- C++11中std::condition_variable的使用
- Ream的入门使用
- cuit校赛--sort 第K个数
- 类加载器
- 查找一个目录下所有视频文件
- Qt中提示“常量中有换行符“的解决方法
- C++11中std::array的使用
- CentOS 7 为firewalld添加开放端口及相关资料
- 基于mysql 批量插入100w测试数据
- JS constructor探讨(一):为什么要设置prototype.constructor?
- GridView的简单使用
- linux 文本处理命令
- tp5文档自动生类
- UML-类图
- 用node.js爬一下优酷