草庐IT

C++ array函数

friendly e 2024-03-22 原文

C++ array

1、前要:

数组是固定大小的序列容器:它们包含按严格的线性顺序排列的特定数量的元素。一个array—也就是容器类array<>的一份实体—模塑出一个static array。它包覆一个寻常的statci C-style array 并提供一个STL容器的接口。

通用格式:arrat<类型名,元素个数>数组名;

注意,因为长度固定,这里的元素个数不能是变量。

array成员函数

函数功能
begin(),end(),cbegin(),cend()提供正向迭代器支持
rbegin(),rend(),crbegin(),crend()提供反向迭代器支持
size()返回数组大小
max_size()返回数组最大大小
empty()判断数组是否为空
at(),operator[]获取数组的元素
front()返回数组第一个元素的引用
back()返回数组最后一个元素的引用
data()返回指向数组对象包含的数据的指针
fill()用值填充数组
swap()交换两个数组元素
get(array)返回某一个数组元素的引用

2、成员函数与用法示例

array用法及初始化

template<class T,size_t N> class array;
//T为所包含元素的类型,别名为成员类型value_type.N的数组大小,以元素数表示。

在使用array前,首先需要添加array这个头文件,即 #include****

注意:array<>是唯一一个无任何东西被指定为初值时,会被预初始化的容器。这就意味着对于基础类型,初值可能不明确,而不是0,下面定义一个有110个int元素的数组arr:

std::array<int,110> arr;
//上面定义的arr并未进行初始化。未初始化将会分配随机值,如下图:

所以尽量不要定义未初始化的数组,否则访问数组元素,而该元素恰好未初始化时,可能出现意想不到的错误。

//array数组对象初始化与标准初始化一摸一样,如:
std::array<int,110>arr{};//将数组所有元素初始化为0
std::array<int, 110>arr{1,2,3,4};//将数组前四个元素分别初始化为1,2,3,4 其余全部为0

fill()

​ fill()函数可以用指定值给数组中所有元素赋值

fill()函数原型如下:

void fill(const value_type &u);//value_type为数组元素类型

【例子】:

#include <iostream>
#include <array>
using namespace std;

int main(){
    std::array<int, 110> arr{1,2,3,4,5,6,7,8,9};
    arr.fill(3);//用3对数组所有元素赋值
    for (auto i:arr) {
        cout<<i<<" ";
    }
    cout<<endl;
    return 0;
}

array元素的获取

  • array元素的获取可以使用下标 [] (与标准数组用法相同),以及STL容器所持有的at()。

  • []与at()的区别在于,[]不会进行检查数字是否越界,at()会进行检查(时间开销很少),如果越界则抛出std::out_of_rang异常。

  • 因此,除非确定访问没有越界,否则应该尽量使用更安全的at()。

  • #include <iostream>
    #include <array>
    using namespace std;
    
    int main(){
        std::array<int, 110> arr{1,2,3,4,5,6,7,8,9};
        arr.at(9) = arr.at(3) + arr.at(5);
        arr[10] = arr[1] + arr[8];
        cout<<arr.at(9)<<endl;
        cout<<arr[10]<<endl;
    //    arr[11]=6;//越界访问,程序异常,但Qt creator并未报错
        arr.at(11) = 6;//异常
        cout<<arr.at(11)<<endl;
        return 0;
    }
    

front()和back()

​ front() 返回数组第一个元素的引用

​ back()返回数组最后一个元素的引用

#include <iostream>
#include <array>
using namespace std;

int main(){
    std::array<int, 11> arr{1,2,3,4,5,6,7,8,9};
    arr.front() = 666;
    arr.back() = 666;
    for(auto i:arr){
        cout<<i<<" ";
    }
    cout<<endl;
    return 0;
}

程序运行结果:

666 2 3 4 5 6 7 8 9 0 666

data()

​ 返回指向数组对象中第一个元素的指针,该元素无参数

#include <iostream>
#include<cstring>
#include <array>
using namespace std;

int main(){
    std::array<int, 10> arr{1,2,3,4,5,6,7,8,9};
    
    cout << *arr.data()<<endl;
    cout << *(arr.data()+6)<<endl;
    
    const char *str = "Test string";
    std::array<char, 12> charray;
    std::memcpy(charray.data(), str, charray.size());
    
    cout << charray.data() << endl;
    return 0;
}

程序运行结果为:

1

7

Test string

size() 和 max_size()

​ 由于array在创建的时候必须明确指定大小,而且array为固定容器,因此size()与max_size()的返回值是相同的,通常使用size()函数。

返回值类型size_t即无符号整数。

使用size()可以有效避免使用for遍历数组时,发生越界的情况。同时它也使得你在写程序的时候,不必去花心思记忆数组大小。

std::array<int , 1o> arr{1,2,3,4,5,6,7,8,9,10};

for(unsigned int i(0);i < arr.size();i++){
		cout<<arr[i]<<" ";
cout << endl;
}

empty()

该函数在array中为鸡肋函数,因为array在定义的时候已经指明了大小,不可能为空。

Tuple接口

array提供tuple接口。因此可以使用表达式tuple_size<>::value取得元素个数,用tuple_element<>::type取得特定元素的类型,用get<>()取得某特定元素。

get()

get()函数为非成员函数重载。

该函数返回array中指定元素的引用。

函数原型如下:

template <size_t I,class T , size_t N>T & get(array<T, N>& arr)noexcept;
template <size_t I,class T , size_t N>T && get(array<T, N>&& arr)noexcept;
template <size_t I,class T , size_t N>const T & get(const array<T, N>& arr)noexcept;
//参数I为:元素在数组中的位置,第一个元素的位置为0.
//参数T为:数组中包含的元素模型(通常从arr隐式获取)。
//参数N为:数组的大小,以元素数为单位(通常从arr隐式中获得)。
//由于参数T、N可以从arr中隐式中获取,所以使用的时候不显示指定二者。
/*
		注意参数I必须明确为数字,不能使用变量,下面为错误用例
*/
int n = 3;
std::get<n>(arr);

例如

#include<cstring>
#include <array>
using namespace std;

int main(){
    std::array<int, 10 > arr{1,2,3,4,5,6,7,8,9,10};
    int a = std::get<6>(arr);
    cout<<a<<endl;
    
    std::get<5>(arr) = 666;
    for (auto i : arr) {
        cout<<i<<" ";
    }
    cout<<endl;
    return 0;
}

程序运行结果如下:

7

1 2 3 4 5 666 7 8 9 10

tuple_size ::value 、、tuple<i,tupleType>::type

在array中用途不大,示例如下:

#include <iostream>
#include<cstring>
#include <array>
using namespace std;

int main(){
    std::array<string, 5> arr = {"one","two","three","four","five"};
    //返回元素的个数,或者说是元组的长度
    cout<<std::tuple_size<decltype(arr)>::value<<endl;
    
    
    //type为array第二个成员变量类型,string型
    std::tuple_element<1,decltype(arr)>::type type;
    type = get<1>(arr);
    cout<<type<<endl;
    
    return 0;
    
}

/*
	补充decltype相关的知识:
	(1)decltype含义和举例:用于推导类型
*	1 decltype对于给定的变量名或者表达式,decltype能够告诉你该名字或者表达式的类型
*		从表达式的类型推断出要定义的变量类型,并且不想初始化变量--使用decltype
*		decltype说明符:主要作用:返回操作数的数据类型
*
*		decltype的特点:
*			1.decltype的自动类型推断会发生在编译期间
*			2.decltype不会真正计算表达式的值
*	1.1decltype后的圆括号是个变量
*	1.2decltype后的圆括号是个不是个变量,表达式。返回表达式结果对应类型
*	1.3decltype后的圆括号是个函数--返回值是函数返回值类型
*
/

array元素的修改

array元素的修改与标准数组用法几乎相同,如:

std::array<int , 10> arr{1,2,3,4,5,6,7,8,9,10};
arr[3] = 6;
arr[2] = arr[0] + arr[1];

同样可以使用指针,引用对其进行修改。

不同于标准数组的是,只要array类型的数组的数据类型和数组长度都相同的话,可以直接用数组B的值覆盖数组A的值,“=”。

#include <iostream>
#include<cstring>
#include <array>
using namespace std;

int main(){
    std::array<int , 3> arr_1{1,2,3};
    std::array<int, 3> arr_2{4,5,6};
    
    arr_2 = arr_1;//用arr_1的元素覆盖arr_2的元素
    
    for (auto i : arr_1) {
        cout<<i<<" ";
    }
    cout<<endl;
    
    for (auto i : arr_1) {
        cout<<i<<" ";
    }
    cout<<endl;
    
    return 0;
    
}

程序运行结果为:

1 2 3

1 2 3

swap()

交换两个array的值,注意:这两个数组的大小和数据类型必须相同。

无返回值,无参数。线性操作(效率较低)

#include <iostream>
#include<cstring>
#include <array>
using namespace std;

int main(){
    std::array<int , 10> arr_1{1,2,3,4,5,6,7,8,9,10};
    std::array<int, 10> arr_2{0,0,0,0,0,0,0,0,0,1};
    
    arr_1.swap(arr_2);
    for (auto i : arr_1) {
            cout<<i<<" ";
        }
        cout<<endl;
        
        for (auto i : arr_2) {
            cout<<i<<" ";
        }
        cout<<endl;
        
        return 0;
}

程序运行结果如下:

0 0 0 0 0 0 0 0 0 1

1 2 3 4 5 6 7 8 9 10

array迭代器

名称功能
begin()返回指向数组第一个元素的迭代器
end()返回指向数组最后一个元素后紧跟的理论元素迭代器
cbegin()返回指向数组第一个元素的const类型迭代器
cend()返回指向数组最后一个元素后紧跟的理论元素的const类型迭代器
rbegin()返回一个反向的迭代器,该迭代器指向数组的最后一个元素
rend()返回一个反向迭代器,该迭代器指向数组第一个元素之前的理论元素
crbegin()返回一个const类型反向迭代器,该迭代器指向数组最后一个一个元素
crend()返回一个const类型反向迭代器,该迭代器指向数组第一个元素之前的理论元素
下面为数组迭代器的简单用法:
#include <iostream>
#include <array>
using namespace std;

int main(){
    std::array<int, 10> arr{1,2,3,4,5,6,7,8,9,10};
    
    array<int, 10>::iterator it_beg = arr.begin();
    array<int, 10>::reverse_iterator rit_beg = arr.rbegin();
    
    for (; it_beg!=arr.end(); it_beg++) {
        cout<<*it_beg*2<<" "; //二倍输出
    }
    cout<<endl;
    
    for (; rit_beg!=arr.rend(); rit_beg++) {
        cout<<*rit_beg<<" ";//倒序输出数组元素
    }
    cout<<endl;
    
    return 0;
}

在使用时最好使用全局的begin()和end()函数从容器中获取迭代器,因为它们是通用的。

如上述array<int, 10>::iterator it_beg = arr.begin();可以改为一下语句

array<int, 10>::iterator it_beg = std::arr.begin();

array元素的比较

可以用任何比较运算符比较两个数组容器,只要它们有相同的大小,保存的是相同的元素,而且这种类型的元素还要支持比较运算符。示例如下:

#include <iostream>
#include <array>
using namespace std;

int main(){
    std::array<int, 3 >arr_1{1,2,3};
    std::array<int, 3>arr_2{1,2,3};
    std::array<int, 3> arr_3{1,3,2};
    
    if (arr_1 == arr_2) {
        cout<<"arr_1 = arr_2"<<endl;
    }
    
    if (arr_1!=arr_3) {
        cout<<"arr_1!=arr_3"<<endl;
    }
    
    if (arr_1 < arr_3) {
        cout << "arr_1 < arr_3" << endl;
    }
    
    return 0;
}

代码运行结果如下:

arr_1 = arr_2

arr_1!=arr_3

arr_1 < arr_3

有关C++ array函数的更多相关文章

  1. ruby - 在 Ruby 中实现 `call_user_func_array` - 2

    我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)

  2. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

    通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

  3. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  4. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  5. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  6. arrays - 这是 Ruby 中 Array.fill 方法的错误吗? - 2

    这个问题在这里已经有了答案:Arraysmisbehaving(1个回答)关闭6年前。是否应该这样,即我误解了,还是错误?a=Array.new(3,Array.new(3))a[1].fill('g')=>[["g","g","g"],["g","g","g"],["g","g","g"]]它不应该导致:=>[[nil,nil,nil],["g","g","g"],[nil,nil,nil]]

  7. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  8. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  9. ruby-on-rails - 将字符串转换为 ruby​​-on-rails 中的函数 - 2

    我需要一个通过输入字符串进行计算的方法,像这样function="(a/b)*100"a=25b=50function.something>>50有什么方法吗? 最佳答案 您可以使用instance_eval:function="(a/b)*100"a=25.0b=50instance_evalfunction#=>50.0请注意,使用eval本质上是不安全的,尤其是当您使用外部输入时,因为它可能包含注入(inject)的恶意代码。另请注意,a设置为25.0而不是25,因为如果它是整数a/b将导致0(整数)。

  10. ruby - Arrays Sets 和 SortedSets 在 Ruby 中是如何实现的 - 2

    通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复

随机推荐