C++ <vector> data 函数
data 是 vector 中一个非常特殊的函数,它返回指向底层数组的指针,让你能够像使用 C 数组一样使用 vector。
data 是容器类的成员函数,用于返回指向容器内部数据存储的指针。这使得 vector 可以与 C 风格 API 或其他需要原始指针的代码互操作。
data 提供了 vector 与 C 语言代码的桥梁,是 vector 强大兼容性的体现。
单词释义: data 就是"数据",表示获取底层数据的指针。
基本语法与参数
data 是容器类的成员函数,调用它不需要参数。
语法格式
T* data(); const T* data() const;
参数说明
- 参数: 无参数
data不接受任何参数。
函数说明
- 返回值: 返回指向底层数组的指针。如果容器是常量容器,则返回常量指针。
- 效果: 返回的指针指向容器的第一个元素,相当于
&operator[](0)。 - 注意: 如果容器为空,返回的指针是未定义的(但通常不是空指针)。
实例
让我们通过一系列例子,彻底掌握 data 的用法。
示例 1:基础用法 - 获取底层数组指针
实例
#include <iostream>
#include <vector>
int main() {
// 1. 创建一个 vector
std::vector<int> numbers = {10, 20, 30, 40, 50};
std::cout << "vector的大小是: " << numbers.size() << std::endl;
// 2. 使用 data 获取底层数组指针
int* ptr = numbers.data();
std::cout << "通过指针访问: " << std::endl;
for(size_t i = 0; i < numbers.size(); ++i) {
std::cout << "ptr[" << i << "] = " << ptr[i] << std::endl;
}
return 0;
}
#include <vector>
int main() {
// 1. 创建一个 vector
std::vector<int> numbers = {10, 20, 30, 40, 50};
std::cout << "vector的大小是: " << numbers.size() << std::endl;
// 2. 使用 data 获取底层数组指针
int* ptr = numbers.data();
std::cout << "通过指针访问: " << std::endl;
for(size_t i = 0; i < numbers.size(); ++i) {
std::cout << "ptr[" << i << "] = " << ptr[i] << std::endl;
}
return 0;
}
运行结果预期:
vector的大小是: 5 通过指针访问: ptr[0] = 10 ptr[1] = 20 ptr[2] = 30 ptr[3] = 40 ptr[4] = 50
代码解析:
numbers.data()返回指向第一个元素的指针。- 通过返回的指针,可以使用数组下标语法访问所有元素。
示例 2:通过指针修改元素
data 返回的指针可以用于修改元素。
实例
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {10, 20, 30};
std::cout << "修改前: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
// 通过 data() 获取指针并修改元素
int* ptr = numbers.data();
ptr[0] = 100;
ptr[1] = 200;
ptr[2] = 300;
std::cout << "修改后: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
#include <vector>
int main() {
std::vector<int> numbers = {10, 20, 30};
std::cout << "修改前: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
// 通过 data() 获取指针并修改元素
int* ptr = numbers.data();
ptr[0] = 100;
ptr[1] = 200;
ptr[2] = 300;
std::cout << "修改后: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
运行结果预期:
修改前: 10 20 30 修改后: 100 200 300
代码解析:
- 通过
data()返回的指针可以直接修改 vector 的内部数据。
示例 3:与 C 风格 API 交互
data 的主要用途之一是与需要数组指针的 C 函数交互。
实例
#include <iostream>
#include <vector>
#include <cstring> // for memset
// 一个假设的 C 风格函数,计算数组总和
int sumArray(const int* arr, size_t size) {
int sum = 0;
for(size_t i = 0; i < size; ++i) {
sum += arr[i];
}
return sum;
}
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用 data() 将 vector 传递给 C 风格函数
int total = sumArray(numbers.data(), numbers.size());
std::cout << "数组元素: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
std::cout << "总和: " << total << std::endl;
return 0;
}
#include <vector>
#include <cstring> // for memset
// 一个假设的 C 风格函数,计算数组总和
int sumArray(const int* arr, size_t size) {
int sum = 0;
for(size_t i = 0; i < size; ++i) {
sum += arr[i];
}
return sum;
}
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
// 使用 data() 将 vector 传递给 C 风格函数
int total = sumArray(numbers.data(), numbers.size());
std::cout << "数组元素: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
std::cout << "总和: " << total << std::endl;
return 0;
}
运行结果预期:
数组元素: 1 2 3 4 5 总和: 15
代码解析:
numbers.data()将 vector 的内部数组指针传递给接受const int*的函数。- 这展示了 vector 与 C 代码无缝交互的能力。
示例 4:使用 memset 操作内存
可以通过 data() 直接操作 vector 的底层内存。
实例
#include <iostream>
#include <vector>
#include <cstring> // for memset
int main() {
std::vector<int> numbers = {10, 20, 30, 40, 50};
std::cout << "清零前: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
// 使用 memset 将所有字节设置为 0
// 注意:这只对整数类型有效,复杂类型可能出问题
std::memset(numbers.data(), 0, numbers.size() * sizeof(int));
std::cout << "清零后: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
#include <vector>
#include <cstring> // for memset
int main() {
std::vector<int> numbers = {10, 20, 30, 40, 50};
std::cout << "清零前: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
// 使用 memset 将所有字节设置为 0
// 注意:这只对整数类型有效,复杂类型可能出问题
std::memset(numbers.data(), 0, numbers.size() * sizeof(int));
std::cout << "清零后: ";
for(int n : numbers) {
std::cout << n << " ";
}
std::cout << std::endl;
return 0;
}
运行结果预期:
清零前: 10 20 30 40 50 清零后: 0 0 0 0 0
代码解析:
data()允许直接操作 vector 的底层内存。- 使用
memset可以快速将所有元素设置为零。 - 注意:这种方法不适用于包含构造函数的对象类型。
示例 5:返回指针的安全使用
当 vector 被重新分配内存时,之前获取的指针会失效。
实例
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3};
// 获取 data 指针
int* ptr = numbers.data();
std::cout << "原始指针指向的值: " << *ptr << std::endl;
// 添加元素可能导致内存重新分配
numbers.push_back(4);
numbers.push_back(5);
numbers.push_back(6);
numbers.push_back(7);
numbers.push_back(8);
numbers.push_back(9);
numbers.push_back(10);
// 警告:ptr 可能已经失效!
// 在现代实现中,通常不会重新分配,但不应该依赖这一点
std::cout << "添加元素后,data() 指针指向的值: " << *(numbers.data()) << std::endl;
// 安全的做法:每次使用 data() 获取新指针
ptr = numbers.data();
std::cout << "重新获取指针后: " << *ptr << std::endl;
return 0;
}
#include <vector>
int main() {
std::vector<int> numbers = {1, 2, 3};
// 获取 data 指针
int* ptr = numbers.data();
std::cout << "原始指针指向的值: " << *ptr << std::endl;
// 添加元素可能导致内存重新分配
numbers.push_back(4);
numbers.push_back(5);
numbers.push_back(6);
numbers.push_back(7);
numbers.push_back(8);
numbers.push_back(9);
numbers.push_back(10);
// 警告:ptr 可能已经失效!
// 在现代实现中,通常不会重新分配,但不应该依赖这一点
std::cout << "添加元素后,data() 指针指向的值: " << *(numbers.data()) << std::endl;
// 安全的做法:每次使用 data() 获取新指针
ptr = numbers.data();
std::cout << "重新获取指针后: " << *ptr << std::endl;
return 0;
}
代码解析:
- 当 vector 容量不足时,
push_back会导致内存重新分配。 - 重新分配后,原来的
data()返回的指针会失效(变成悬空指针)。 - 安全做法:每次使用时重新调用
data(),或使用reserve()预分配足够空间。

C++ 容器类 <vector>