参考:
http://topic.csdn.net/t/20050429/20/3976956.html
不过那边是转载自《effective stl》。
std::vector很方便,但有时调用的函数的参数规定是数组,需要将vector转为数组,另外开辟一个空间,将vector一项项复制过去代价过大,可用下面的方法。
给定一个
vector<int> v;
表达式v[0]生产一个指向vector中第一个元素的引用,所以,&v[0]是指向那个首元素的指针。vector中的元素被C++标准限定为存储在连续内存中,就像是一个数组,所以,如果我们想要传递v给这样的C风格的API:
void doSomething(const int* pInts, size_t numInts);
我们可以这么做:
doSomething(&v[0], v.size());
也许吧。可能吧。唯一的问题就是,如果v是空的。如果这样的话,v.size()是0,而&v[0]试图产生一个指向根本就不存在的东西的指针。这不是件好事。其结果未定义。一个较安全的方法是这样:
if (!v.empty()) {
doSomething(&v[0], v.size());
}
如果你在一个不好的环境中,你可能会碰到一些半吊子的人物,他们会告诉你说可以用v.begin()代替&v[0],因为(这些讨厌的家伙将会告 诉你)begin返回指向vector内部的迭代器,而对于vector,其迭代器实际上是指针。那经常是正确的,但正如条款50所说,并不总是如此,你 不该依赖于此。begin的返回类型是iterator,而不是一个指针,当你需要一个指向vector内部数据的指针时绝不该使用begin。如果你基 于某些原因决定键入v.begin(),就应该键入&*v.begin(),因为这将会产生和&v[0]相同的指针,这样可以让你有更多 的打字机会,而且让其他要弄懂你代码得人感觉到更晦涩。坦白地说,如果你正在和告诉你使用v.begin()代替&v[0]的人打交道的话,你该 重新考虑一下你的社交圈了。(译注:在VC6中,如果用v.begin()代替&v[0],编译器不会说什么,但在VC7和g++中这么做的话, 就会引发一个编译错误)
不必复制数据。
std::vector,内部存储的所有元素,都是占用一片连续的内存空间。因此,比较好的做法就是直接取第一个元素的地址,得到了首地址,之后的做法与数组也是大同小异了。
举例说明。
假设函数Func需要以数组的方式传递,函数原型如下:
void Func(double* pDataAddress, size_t nDataCount);
那么,如果使用数组,调用的方法如下:
double data[30];
Func(data, 30);
而使用vector,调用的方法如下:
std::vector<double> data(30);
Func(&data[0], data.size());
需要注意的地方:
1、如果vector长度为零,那就不能取得第一个元素的地址。因为此时第一个元素还不存在。程序注意判断。
2、如果vector的长度变长(例如:不停地进行push_back),那可能导致之前取得的地址变为无效。为了安全,每次进行push_back, insert, assign之类的操作之后,就需要重新取得第一个元素的地址。因为之前取得的地址可能已经无效了。
相关推荐
在C++编程中,将CSV(逗号分隔值)文件读取到数组是一项常见的任务,特别是在处理数据或实现数据分析程序时。CSV文件通常用于存储表格数据,每一行代表一个记录,每一列代表一个属性,列之间用逗号分隔。在本教程中...
在标准库中,`std::getline` 和 `cin.getline` 提供了这样的功能,但它们并不直接适用于动态数组,特别是`std::vector<char>`类型的动态数组。本篇文章将详细探讨如何在C++中使用`std::vector<char>`实现整行输入,...
在编程领域,尤其是在使用C++、Java或C#等面向对象的语言时,经常需要将字符串数组转换为单一的string类型。这种操作在处理数据输入、输出或者格式化时非常常见。下面我们将详细讨论如何在不同语言中实现这个过程,...
- **用途**:提供了动态数组的功能。 - **关键函数**: - `push_back(val)` —— 向向量末尾添加元素。 - `at(idx)` —— 访问向量指定位置的元素。 - **示例**: ```c++ #include <vector> int main() { ...
1. 容器:如vector(动态数组)、list(双向链表)、deque(双端队列)、set(集合)、map(映射)等,它们提供了存储和管理数据的结构。容器可以根据需求选择不同的数据结构,以适应各种场景。 2. 迭代器:迭代器...
7. 数组:MongoDB的Array对应C++的std::vector或其他容器。 8. 文档:MongoDB的Document对应C++的BSON对象,可以使用BSON库进行操作。 9. 二进制数据:MongoDB的Binary对应C++的std::vector或其他二进制数据容器。 ...
- **vector**: 动态数组实现,支持随机访问。 - **deque**: 双端队列实现,两端都可以快速插入和删除。 - **list**: 双向链表实现,适合频繁插入和删除的场景。 #### 关联式容器 - **set**: 存储唯一元素,按排序...
- 使用`static_cast`、`dynamic_cast`、`reinterpret_cast`和`const_cast`进行类型转换,以增强代码的类型安全性。 6. **代码组织**: - 使用头文件(`.h`/`.hpp`)和实现文件(`.cpp`/`.cc`)分离,以提高编译...
7. **编译与链接**:C/C++程序需要先经过编译器转换为中间的汇编代码,再链接成可执行文件。编译错误和链接错误是常见的问题。 8. **错误处理**:通过return语句或异常处理(C++特有的)来处理程序运行时可能出现的...
理解指针运算、指针数组、指针作为函数参数和返回值是基础。 - 引用是C++特有的特性,它是一种安全的别名,一旦引用被初始化,就不能改变引用的对象。 2. **内存管理** - 理解堆栈与堆的区别:栈内存由编译器自动...
4. **初始化列表(Initializer Lists)**:初始化列表允许在创建对象或数组时使用花括号来指定初始值,对于构造带有多个构造函数的对象特别有用,同时它也用于`std::map`、`std::vector`等容器的初始化。 5. **类型...
- **动态数组(vector)**:C++的`std::vector`提供动态数组功能,方便存储和管理学生对象。 6. **异常处理(Exception Handling)** - **try-catch块**:用于捕获可能出现的错误,如内存分配失败、文件操作异常...
2. `<vector>`:STL中的动态数组,可以方便地增加和删除元素,支持下标访问和迭代器操作。 3. `<list>`:STL中的链表容器,适用于频繁插入和删除操作。 4. `<set>`:STL中的关联容器,实现了一个排序的唯一元素集合...
C++标准库提供了解决这个问题的容器,如std::vector,它允许动态增长和收缩。 6. 函数和过程: - Delphi中有函数和过程的区别,函数返回值,而过程不返回。 - C++中的函数都可以返回值,如果不需要返回值,通常会...
这个代码首先定义了一个二维数组`board`模拟棋盘,然后使用三个一维数组`col`, `dia1`和`dia2`记录每行的列冲突、两种对角线冲突的状态。`backtrack`函数通过递归实现回溯过程,每次尝试在新的行放置皇后,如果成功...
- **C++**:可以使用`std::stringstream`和`std::hex`来解析16进制字符串,然后使用`std::vector<unsigned char>`存储结果。 5. **下位机通信中的应用**: - **编程固件**:在更新微控制器或嵌入式系统的固件时,...
### C++ 四种强制类型转换的总结 在C++编程语言中,为了实现不同数据类型之间的转换,提供了四种不同的强制类型转换操作符:`static_cast`、`const_cast`、`dynamic_cast` 和 `reinterpret_cast`。这些操作符不仅在...
总之,通过使用`std::vector`和字符级的读取操作,我们可以有效地将多行数字输入转换为可操作的数组。这个实例代码提供了一个基础的解决方案,但在实际应用中,可能需要根据具体需求进行调整和优化。例如,处理异常...
- 容器(容器类模板):如vector、list、deque、set、map等,提供动态数组、链表、双端队列、集合和关联映射等功能。 - 队列和栈(queue和stack):实现FIFO(先进先出)和LIFO(后进先出)数据结构。 - 链表算法...