数组

一、数组的两个特殊性质

(1)不允许拷贝和赋值

  不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值。

int a[] = {0,1,2};    // 含有三个整数的数组
int s2 = a;           // 错误:不允许使用一个数组初始化另一个数组
a2 = a;               // 错误:不能把一个数组直接赋值给另一个数组

数组的拷贝可以使用memcpy()函数:

int des[5], src[3]

memcpy(des, src, sizeof(src));

(2)使用数组是通常将其转化成指针

  在C++语言中,指针和数组有非常紧密的联系。使用数组的时候编译器一般会把它转换成指针。

  通常情况下,使用取地址符来获取指向某个对象的指针,取地址符也可以用于任何对象。数组的元素也是对象,对数组使用下标运算符得到该数组指定位置的元素。因此像其他对象一样,对数组的元素使用取地址符就能的搭配指向该元素的指针:

string nums[] = {"one", "two", "three"};  // 数组元素是string对象
string *p = &nums[0];                     // p指向nums的第一个元素

例子:

char pdata[256];
memset(pdata, 0, sizeof(pdata));
sprintf(pdata, "sdk(1) send rs485 data to camera.");
int len = strlen(pdata);

//第二个形参类型时char *
TransSerialPort(m_hSDK[0], pdata, len+1);//发送rs485数据

 

当使用vector<char> pdata时:

TransSerialPort(m_hSDK[0], &pdata[0], len+1);//发送rs485数据

 

 然而,数组还有一个特性:在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向数组首元素的指针:

string *p2 = nums;                        // 等价于p2 = &nums[0]

在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针。

 

 

二、数组作为函数参数

 

 数组的两个特殊性质对我们定义和使用作用在数组上的函数有影响。因为不能拷贝数组,所以我们无法以值传递的方式使用数组参数。因为数组会被转换成指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的指针。 
 尽管不能以值传递的方式传毒数组,但是我们可以把形参写成类似数组的形式:


在数组中,值传递就是指针地址的传递,对于数组来说却是一个例外,因为数组的数据太多了,将其一一赋值既麻烦又浪费空间,所以数组作为参数传递给函数的只是数组首元素的地址,函数在需要用到后面元素时再按照这个地址和数组下标去查找,在C++中,如果要给一个函数传入一个数组,一般都是传入两个参数:一个数组指针和一个数组大小。所以,函数调用的数组会对本身的数组造成影响,这点和值传递是不同的。

同时,作为函数形参的数组和指针可以互换,这种转换仅限于函数形参的声明。这是一种便利,传递时数组会蜕变为指针,事实上数组从来没有传入过函数。
eg:以下3个声明是等价的

  1. void insert(int *);  
  2. void insert(int []);  
  3. void insert(int [10]);   //这里的维度表示我们期望数组含有多少元素,实际不一定

数组长度不是参数类型的一部分。函数和编译器都不知道传统给它的数组的长度的大小。

 

 

2.如果我们要传入指定长度数组,又该怎么办呢?

我们可以将参数声明为数组的引用,此时,数组长度成为形参和实参的一部分。

eg:void insert( int (&arr)[10])

 

例如:

void print_3 (int (&datas) [3])
{
    for (int i = 0; i < 3; ++i)
    {
        std::cout << datas[i] << " ";
    }
    std::cout << std::endl;
}

这时,我们如果这样使用是正确的
const int N = 3;
int datas[N] = {1, 2, 3};
print_3 (datas);

而我们如果这样使用,编译器会报错
int datas2[N - 1] = {1, 2};
print_3 (datas2);


在上面这个例子(print_3)的基础上,我们可以使用模板进行泛型实现
template<int N>
void print_4 (int (&datas)[N]) 
{
    for (int i = 0; i < N; ++i)
    {
        std::cout << datas[i] << " ";
    }
    std::cout << std::endl;
}

这时候,我们可以传递任意大小数组,而不担心给函数传入了错误的参数
const int N = 3;
int datas[N] = {1, 2, 3};
print_4 (datas);

int datas2[N - 1] = {1, 2};
print_4 (datas2);

假如我们给传了错误参数,函数将会报错
const int N = 3;
int datas[N] = {1, 2, 3};
print_4<4 > (datas);

 

 

 

 

参考资料:

详谈C++中数组作为函数参数 - CSDN博客  http://blog.csdn.net/oNever_say_love/article/details/49422517

C++学习笔记(四)——关于数组作为函数参数的值传递和引用传递 - CSDN博客  http://blog.csdn.net/ForeverSober/article/details/45441685

C++给函数传数组参数 - CSDN博客  http://blog.csdn.net/hongjiqin/article/details/5739935

 

C语言中值得深入知识点----数组做函数参数、数组名a与&a区别、数组名a的"数据类型" - CSDN博客  http://blog.csdn.net/jin13277480598/article/details/51891816

 

posted on 2018-01-12 14:13  南枝  阅读(222)  评论(0编辑  收藏  举报