C++笔记之动态数组的申请和手动实现一个简单的vector
code review!
文章目录
1.C语言中动态数组的申请与使用
在C语言中,可以使用malloc
函数来动态申请内存以创建动态数组,并使用free
函数来释放这些内存。以下是在C语言中创建和使用动态数组的基本示例:
代码
c
#include <stdio.h>
#include <stdlib.h>
int main() {
int size;
printf("Enter the size of the dynamic array: ");
scanf("%d", &size);
// 使用malloc函数分配动态数组内存
int *dynamicArray = (int *)malloc(size * sizeof(int));
// 检查内存分配是否成功
if (dynamicArray == NULL) {
printf("Memory allocation failed.\n");
return 1; // 返回错误码
}
// 初始化动态数组的元素
for (int i = 0; i < size; i++) {
dynamicArray[i] = i * 2;
}
// 访问和使用动态数组的元素
for (int i = 0; i < size; i++) {
printf("%d ", dynamicArray[i]);
}
// 释放动态数组内存
free(dynamicArray);
return 0;
}
在上述示例中,首先使用malloc
函数分配了一块内存,该内存可以存储size
个int
类型的元素。然后,通过循环初始化和使用动态数组的元素。最后,使用free
函数释放分配的内存以防止内存泄漏。
请注意,使用malloc
和free
来管理内存需要特别小心,确保在不再需要动态数组时释放内存,以免出现内存泄漏。此外,动态数组的内存大小必须在运行时明确定义,并且需要手动处理分配和释放内存,这可能会引入错误,因此要特别小心。如果可能的话,推荐使用C++中的std::vector
或C语言的动态数组分配方式,如alloca
或strdup
,以减少手动内存管理的复杂性。
1.动态数组的申请
在C++中,可以使用new
运算符来动态申请数组,并使用delete
运算符来释放它们。此外,C++11引入了std::vector
,它是一个动态数组的封装,提供了更方便和安全的方法来管理动态数组。下面分别介绍使用new
和std::vector
的方法来创建和使用动态数组。
使用new
和delete
代码
cpp
#include <iostream>
int main() {
int size;
std::cout << "Enter the size of the dynamic array: ";
std::cin >> size;
// 通过new运算符分配动态数组
int* dynamicArray = new int[size];
// 初始化动态数组的元素
for (int i = 0; i < size; i++) {
dynamicArray[i] = i * 2;
}
// 访问和使用动态数组的元素
for (int i = 0; i < size; i++) {
std::cout << dynamicArray[i] << " ";
}
// 释放动态数组内存
delete[] dynamicArray;
return 0;
}
使用new
分配动态数组后,不要忘记使用delete[]
释放内存,以防止内存泄漏。
使用std::vector
使用std::vector
可以更方便地管理动态数组,无需手动分配和释放内存:
cpp
#include <iostream>
#include <vector>
int main() {
int size;
std::cout << "Enter the size of the dynamic array: ";
std::cin >> size;
// 使用std::vector创建动态数组
std::vector<int> dynamicArray(size);
// 初始化动态数组的元素
for (int i = 0; i < size; i++) {
dynamicArray[i] = i * 2;
}
// 访问和使用动态数组的元素
for (int i = 0; i < size; i++) {
std::cout << dynamicArray[i] << " ";
}
return 0;
}
std::vector
会自动处理内存分配和释放,使得代码更加安全和易维护。
无论您选择使用new
和delete
还是std::vector
,都要确保正确管理动态数组的内存,以防止内存泄漏和访问越界错误。
1.std::vector的底层实现
C++中的vector
是标准库中的一个动态数组容器,它提供了动态大小的数组,类似于C数组,但它具有自动管理内存的功能,可以动态增加或减少数组的大小。vector
的底层实现通常是使用动态分配的数组,以及一些成员函数来管理这个数组的大小和元素。
下面是vector
的一些常见底层实现细节:
-
动态分配的数组:
vector
内部通常使用一个指向动态分配的数组的指针来存储元素。这个数组的大小可以根据vector
中存储的元素数量动态调整。当元素数量超过当前数组的容量时,vector
会分配一个更大的数组,将元素从旧数组复制到新数组,然后释放旧数组。 -
容量(Capacity)和大小(Size):
vector
有两个重要的属性,容量和大小。容量表示当前数组的大小,而大小表示vector
中实际存储的元素数量。容量通常大于或等于大小,因为vector
可能会提前分配一些额外的空间,以减少频繁重新分配内存的开销。 -
动态调整容量:当
vector
的大小超过容量时,它会重新分配更大的内存块,并将元素从旧数组复制到新数组。这通常涉及到内存分配和复制操作,这可能会导致性能开销。为了减小重新分配的频率,vector
通常会分配比当前大小更多的额外空间,以避免在每次插入元素时都重新分配内存。 -
内存管理:
vector
负责动态内存的分配和释放,以确保内存的正确管理。当vector
不再需要某个内存块时,它会调用delete[]
或allocator::deallocate
来释放内存。 -
迭代器:
vector
提供了迭代器,用于访问容器中的元素。迭代器是指向容器中元素的指针或对象,允许你遍历vector
的内容。
总之,vector
的底层实现是基于动态分配的数组,它使用内部指针来管理内存,并提供了各种方法来操作容器中的元素,包括插入、删除、访问等。这些实现细节在C++标准库中是隐藏的,因此你可以方便地使用vector
而无需担心底层实现的细节。
2.手动实现一个简单的vector:使用一个指向动态分配的数组的指针来存储元素模拟vector的基本行为
运行
代码
cpp
#include <iostream>
class MyVector {
public:
MyVector() : data(nullptr), size(0), capacity(0) {}
void push_back(int value) {
if (size >= capacity) {
// 如果当前大小超过容量,需要重新分配更大的内存
int new_capacity = (capacity == 0) ? 1 : capacity * 2;
int* new_data = new int[new_capacity];
// 将数据从旧数组复制到新数组
for (int i = 0; i < size; i++) {
new_data[i] = data[i];
}
// 释放旧数组的内存
delete[] data;
// 更新指针和容量
data = new_data;
capacity = new_capacity;
}
// 在数组末尾添加新元素
data[size] = value;
size++;
}
int at(int index) {
if (index >= 0 && index < size) {
return data[index];
} else {
std::cerr << "Index out of range!" << std::endl;
return -1;
}
}
int getSize() {
return size;
}
~MyVector() {
delete[] data; // 释放动态分配的内存
}
private:
int* data; // 指向动态分配的数组的指针
int size; // 当前元素数量
int capacity; // 当前容量
};
int main() {
MyVector vec;
// 向自定义的vector中添加一些元素
for (int i = 1; i <= 10; i++) {
vec.push_back(i * 10);
}
// 访问元素并打印
for (int i = 0; i < vec.getSize(); i++) {
std::cout << "Element at index " << i << ": " << vec.at(i) << std::endl;
}
return 0;
}