【C++ STL应用与实现】5: 如何使用std::array (since C++11)
来源:互联网 发布:如何注册域名多少钱 编辑:程序博客网 时间:2024/05/16 23:35
本系列文章的目录在这里:目录. 通过目录里可以对STL总体有个大概了解
前言
本文总结了STL中的序列式容器array的用法及注意事项。array的出现代表着C++的代码更进一步“现代化”,就像std::string的出现代替了c风格字符串并且能和STL配合工作一样,array的出现则将取代语言内置的数组以及c风格的数组字符串,它提供了data()接口,使得能够获得内部数组的首地址,它提供了size(), 能够得其固定的长度,使得C++的数组也可以像Java等语言那样知道自己的length;它提供了begin(), end()等接口使得“数组”也可以和STL血脉相容;它还提供了tuple接口,可以当做tuple来使用;更重要的一点是,array有并不比原生数组差的性能表现。
array的概念
array是STL中的一个序列式容器,它包装了一个c风格的数组,但在外部接口来看,提供了STL容器的常用接口。它的长度是固定的,正如普通的c风格数组那样,一旦创建完成,长度即确定,不能扩大也不能缩小。
它的原型就像这样, 是一个模板类:
namespace std{ template <typename T, size_t N> class array;}
第一个模板参数T指明了array中存放的数据类型;
第二个非类型模板参数
指明了array的固定大小。
array的接口
constructors
arrary<T, N> c
默认构造函数,N个元素全部使用“默认初始化行为”来构造。 arrary<T, N> c(other)
拷贝构造函数,拷贝所有other的元素到c来构造。 arrary<T, N> c = other
拷贝构造函数,拷贝所有other的元素到c来构造。 arrary<T, N> c(rValue)
移动构造,使用右值rValue里的元素来初始化c。 arrary<T, N> c = rValue
移动构造,使用右值rValue里的元素来初始化c。 arrary<T, N> c = initlist
使用初始化列表初始化元素注意: 由于默认构造函数是对每一个元素使用“默认构造”行为来初始化,这意味着对于基本类型的数据其初始值是未定义的。
array 被要求是一个“aggregate”: 没有用户自定义的构造函数、没有非静态的private和protected类型的成员、没有基类、没有虚函数.
因此不支持这样的构造方法:array<int, 3> a({1, 2, 4})
;
初始化array最常用的方法是使用赋值运算符和初始化列表:
array<int, 3> a = {1, 2, 3};array<int, 100> b = {1, 2, 3}; // a[0] ~ a[2] = 1, 2, 3; a[3] ~ a[99] = 0, 0, 0 ... 0;array<int, 3> c; // c[0] ~ c[2] 未初始化,是垃圾值.
assignment
c = other
把other的全部元素复制一份给c。 c = rValue
rValue全部元素被移动到c c.fill(val)
用val给每个元素赋值 c.swap(c2)
交换c和c2的所有元素 swap(c, c2)
交换c和c2的所有元素注意 :array的swap操作通常代价比较高:是一个O(n)的操作。
begin(), end()等迭代器位置及属性获取操作
begin() (cbegin())
end() (cend())
rbegin() (crbegin())
rend() (crend())
empty()
size()
max_size()
[index]
at(index)
- front()
- back();
tuple接口
array<string, 3> a = {"hello", "hwo", "are"};tuple_size<a>::value;tuple_element<1, a>::type; // stringget<1>(a);
把array当做c风格的数组来用
//----------------------- array as c-style array ----------------------RUN_GTEST(ArrayTest, CStyleArray, @);// use array<char> as a fix sized c-string.array<char, 100> str = {0}; // all elements initialized with 0.char *p = str.data();strcpy(p, "hello world");printf("%s\n", p); // hello worldEND_TEST;
上面这个例子让我想起了std::string, 它有一个c_str()方法,同样是返回内部的c风格字符串,同样string也是STL的容器。
这让我想到,array的出现也是像string那样,是为了取代旧的c-风格字符串和内置数组,并且添加了标准容器的一些接口使得数组可以和STL其他组件和谐工作。
综合示例
//----------------------- normal example ----------------------RUN_GTEST(ArrayTest, NormalExample, @);array<int, 5> a = { 1, 2, 3 };psln(a.size()); // a.size() = 5;psln(a.max_size()); // a.max_size() = 5;EXPECT_FALSE(a.empty()); // empty() is false.printContainer(a, "array: "); // array: 1 2 3 0 0a[a.size() - 1] = 5; // change last oneprintContainer(a, "array: "); // array: 1 2 3 0 5a.at(a.size() - 2) = 4;printContainer(a, "array: "); // array: 1 2 3 4 5int sum;sum = accumulate(a.begin(), a.end(), 0);psln(sum); // sum = 15try{ int i = a.at(5); // throw.}catch ( ... ){ pln("exception catched");}try{ //int i = a[5]; // won't throw exception.}catch ( ... ){ pln("exception catched"); }// ------------------ copy ------------------array<int, 5> a2 = a; // copy constructor.printContainer(a2, "a2: "); // a2: 1 2 3 4 5array<int, 5> a3(a2); //copy ctor.printContainer(a3, "a3: "); // a3: 1 2 3 4 5// ------------------ assign ------------------array<int, 5> a4;a4 = a3; // assignment operator.printContainer(a4, "a4: "); // a4: 1 2 3 4 5array<int, 4> b = {};//b = a; // error, b is not array<int, 5>!!// ------------------ fill ------------------array<int, 5> a5;a5.fill(5);printContainer(a5, "a5: "); // a5: 5 5 5 5 5// ------------------ move ------------------// ------------------ array with class objects. ------------------END_TEST;
二维和多维array
//----------------------- multiple div array example ----------------------RUN_GTEST(ArrayTest, MatrixOrMultipleDiv, @);// like plain 2D arrayarray<array<int, 5>, 5> mat1 = { 1,2,3,4,5, 1,2,3,4,5, 1,2,3,4,5, 1,2,3,4,5, 1,2,3,4,5,};// construct with 1D arys.array<int, 5> ary = {1};array<array<int, 5>, 5> mat2 = { ary, ary, ary, ary, ary};// just like plain 2D array, but can ommit some value some each div.array<array<int, 5>, 5> mat3 = { array<int, 5>{ 1, 2, 3, 4, 5}, array<int, 5>{ 1, 2, 3, 4}, array<int, 5>{ 1, 2, 3}, array<int, 5>{ 1, 2,}, array<int, 5>{ 1, }};// util function to print matrix.auto printMatrix = [] (const array<array<int, 5>, 5>& mat) { for (const auto& ary : mat) { for (const auto& item : ary) { cout << item << " "; } cout << endl; }};pcln("ma1");printMatrix(mat1);pcln("mat2");printMatrix(mat2);pcln("mat3");printMatrix(mat3);END_TEST;
output:
************************ma1*********************1 2 3 4 51 2 3 4 51 2 3 4 51 2 3 4 51 2 3 4 5************************mat2*********************1 0 0 0 01 0 0 0 01 0 0 0 01 0 0 0 01 0 0 0 0************************mat3*********************1 2 3 4 51 2 3 4 01 2 3 0 01 2 0 0 01 0 0 0 0
注意事项
swap的代价:O(n)
基本类型的默认构造是垃圾值,用初始化列表来避免
array<int, 3> a; // no.array<int, 3> a = {}; // good.
源码
array_test.cpp
std::array
作者水平有限,对相关知识的理解和总结难免有错误,还望给予指正,非常感谢!
欢迎访问github博客,与本站同步更新
- 【C++ STL应用与实现】5: 如何使用std::array (since C++11)
- 【C++ STL应用与实现】23: 如何使用std::mem_fn (since C++11)
- 【C++ STL应用与实现】7: 如何使用std::forward_list 单链表 (since C++11)
- 【C++ STL应用与实现】22: 函数组合之1:如何使用std::bind (since C++11)
- 【C++ STL应用与实现】26: 如何使用std::for_each以及基于范围的for循环 (since C++11)
- 【C++ STL学习与应用总结】22: 函数组合之1:如何使用std::bind (since C++11)
- 【C++ STL应用与实现】64: 如何使用shuffle和random_shuffle : 洗牌 (since C++11)
- 【C++ STL应用与实现】86: 如何使用std::accumulate
- 【C++ STL应用与实现】62: 如何使用std::next_permutation
- 【C++ STL应用与实现】2: 如何使用std::vector
- 【C++ STL应用与实现】6: 如何使用std::list
- 【C++ STL应用与实现】12: 如何使用std::stack
- 【C++ STL应用与实现】13: 如何使用std::queue和std::priority_queue
- 【语言-C++】STL std::list的使用
- 【C++ STL应用与实现】56: 使用std::unique删除重复元素
- C++: std::string 与 Unicode 如何结合?
- C++: std::string 与 Unicode 如何结合?
- C++: std::string 与 Unicode 如何结合?
- 2-7-集合运算(A-B)∪(B-A)-线性表-第2章-《数据结构》课本源码-严蔚敏吴伟民版
- iOS开发新手
- casperjs爬虫总结 -- (4) 保存到mongo数据库
- TCP/IP协议
- Linux系统防止别人非法进入单用户模式
- 【C++ STL应用与实现】5: 如何使用std::array (since C++11)
- Kafka入门
- 读后有感 - UI设计师必知:线框图、原型和视觉稿
- win7配置maven环境变量
- 单用户模式
- Unity3D-UGUI-drag and drop实现拖拽放下功能
- 不好好说话版原理(一)SSH验证原理
- 浅谈5.7limit优化
- 使用ida调试dex文件