C++中vector构造及数组与int相加的技术疑问
本人具备Java和Python开发背景,但不熟悉C系语言。现遇到一段C代码,该代码通过C包装器调用C代码以提供给Python调用,打算将其改写为Cython,但对其中的C包装器逻辑存在疑问:
代码如下:
extern "C" float wrapped(const unsigned long long* arr, const int len_arr) { std::vector<unsigned long long> arr_vec(arr,arr+len_arr); return SomeObj(arr_vec); }
我了解C++中std::vector有多种初始化方式,原以为arr_vec(arr,arr+len_arr)是填充构造函数,但实际第一个参数是数组而非整数,不符合填充构造的形式。另外,我对第二个参数中将int与unsigned long long类型数组相加的操作感到困惑:在Python的numpy中,arr+1是给数组每个元素加1,但我原以为C系语言不支持这类混合类型操作,因此有两个核心疑问:
- 此处使用的是std::vector的哪种构造函数?该如何通过给定参数初始化vector?
- C++中是否允许数组与int直接相加?这与numpy的操作是否类似?
问题1:std::vector的构造函数类型及初始化逻辑
这里用的是std::vector的范围构造函数,其核心签名为:
template <class InputIterator> vector(InputIterator first, InputIterator last);
在C++里,数组名arr会自动退化为指向数组第一个元素的指针(const unsigned long long*类型),而指针可以直接当作迭代器使用。arr是起始迭代器(指向数组第一个元素),arr+len_arr是结束迭代器(指向数组最后一个元素的下一个位置)。这个构造函数会遍历[first, last)区间内的所有元素,依次将它们拷贝到新创建的arr_vec中,最终得到一个和原数组元素完全一致的vector。
简单来说,就是用原数组的完整元素范围来初始化vector,相当于把数组里的所有元素批量复制进vector容器。
问题2:数组与int相加的本质及和numpy的区别
C++里允许数组名(退化为指针后)和int直接相加,但这和numpy的元素级加法完全不是一回事:
- 在numpy中,
arr+1是对数组的每个元素执行加1操作,属于元素级运算。 - 而C++中,
arr+len_arr是指针地址偏移运算:指针本质是内存地址,加上整数len_arr后,会根据指针指向的类型(这里是unsigned long long)计算偏移量——最终得到的是原地址往后偏移len_arr * sizeof(unsigned long long)字节的新指针。比如arr指向数组第0个元素,arr+1就指向第1个元素,arr+len_arr就指向数组末尾的下一个位置(这个位置本身不存储数组元素,但作为迭代器的结束位置是合法的)。
这种操作和元素本身无关,纯粹是内存地址的计算,和numpy的行为完全不同。
内容的提问来源于stack exchange,提问作者Bram Vanroy

