提供的接口:
2、operator[] =
classDiagram
class Vector {
-size_: size_t
-capacity_: size_t
-data_: T*
+Vector()
+Vector(const Vector& other)
+Vector(Vector&& other) noexcept
+operator=(const Vector& other): Vector&
+operator=(Vector&& other) noexcept: Vector&
+~Vector()
+push_back(U&& value): void
+pop_back(): void
+emplace_back<Args>(Args&&... args): void
+operator[](size_t index): T&
+operator[](size_t index) const: const T&
+size() const: size_t
+capacity() const: size_t
+empty() const: bool
+clear(): void
+resize(size_t new_size): void
+reserve(size_t new_capacity): void
+swap(Vector& other) noexcept: void
}
#include <iostream>
#include <stdexcept>
#include <utility>
template<typename T>
class Vector {
public:
Vector() : size_(0), capacity_(0), data_(nullptr) {}
// copy construct
Vector(const Vector& other) : size_(other.size_), capacity_(other.capacity_), data_(new T[capacity_]) {
for (size_t i = 0; i < size_; i++) {
data_[i] = other.data_[i];
}
}
// move construct
Vector(Vector&& other) noexcept : size_(other.size_), capacity_(other.capacity_), data_(other.data_) {
other.size_ = 0;
other.capacity_ = 0;
other.data_ = nullptr;
}
// copy =
Vector& operator=(const Vector& other) {
if (this != &other) {
delete[] data_;
size_ = other.size_;
capacity_ = other.capacity_;
data_ = new T[capacity_];
for (size_t i = 0; i < size_; i++) {
data_[i] = other.data_[i];
}
}
return *this;
}
// move =
Vector& operator=(Vector&& other) noexcept {
if (this != &other) {
delete[] data_;
size_ = other.size_;
capacity_ = other.capacity_;
data_ = other.data_;
other.size_ = 0;
other.capacity_ = 0;
other.data_ = nullptr;
}
return *this;
}
~Vector() {
if (data_ != nullptr) {
delete[] data_;
}
}
// 这里使用万能引用去捕获左值 右值
template<typename U>
void push_back(U&& value) {
if (size_ == capacity_) {
reserve(capacity_ == 0 ? 1 : capacity_ * 2);
}
data_[size_++] = std::forward<U>(value);
}
void pop_back() {
if (size_ == 0) {
throw std::out_of_range("Vector is empty");
}
--size_;
}
template<typename ... Args>
void emplace_back(Args&& ... args) {
if (size_ == capacity_) {
reserve(capacity_ == 0 ? 1 : capacity_ * 2);
}
new (&data_[size_++]) T(std::forward<Args>(args)...);
}
T& operator[](size_t index) {
if (index >= size_) {
throw std::out_of_range("Index out of range");
}
return data_[index];
}
const T& operator[](size_t index) const {
if (index >= size_) {
throw std::out_of_range("Index out of range");
}
return data_[index];
}
size_t size() const {
return size_;
}
size_t capacity() const {
return capacity_;
}
bool empty() const {
return size_ == 0;
}
void clear() {
size_ = 0;
}
void resize(size_t new_size) {
if (new_size > size_) {
reserve(new_size);
for (size_t i = size_; i < new_size; i++) {
new (&data_[i]) T();
}
} else { // 否则析构掉多余的元素
for (size_t i = new_size; i < size_; i++) {
data_[i].~T();
}
}
size_ = new_size;
}
void reserve(size_t new_capacity) {
if (new_capacity > capacity_) {
T* new_data = new T[new_capacity];
for(size_t i = 0; i < size_; i++) {
new_data[i] = data_[i];
}
delete[] data_;
data_ = new_data;
capacity_ = new_capacity;
}
}
void swap(Vector& other) noexcept {
std::swap(size_, other.size_);
std::swap(capacity_, other.capacity_);
std::swap(data_, other.data_);
}
private:
size_t size_;
size_t capacity_;
T* data_;
};
int main() {
Vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
std::cout << "v: ";
for (size_t i = 0; i < v.size(); ++i) {
std::cout << v[i] << " ";
}
std::cout << std::endl;
Vector<int> v2(v);
std::cout << "v2: ";
for (size_t i = 0; i < v2.size(); ++i) {
std::cout << v2[i] << " ";
}
std::cout << std::endl;
Vector<int> v3(std::move(v));
std::cout << "v3: ";
for (size_t i = 0; i < v3.size(); ++i) {
std::cout << v3[i] << " ";
}
std::cout << std::endl;
Vector<int> v4;
v4 = v2;
std::cout << "v4: ";
for (size_t i = 0; i < v4.size(); ++i) {
std::cout << v4[i] << " ";
}
std::cout << std::endl;
Vector<int> v5;
v5 = std::move(v3);
std::cout << "v5: ";
for (size_t i = 0; i < v5.size(); ++i) {
std::cout << v5[i] << " ";
}
std::cout << std::endl;
v5.resize(5);
std::cout << "v5: ";
for (size_t i = 0; i < v5.size(); ++i) {
std::cout << v5[i] << " ";
}
std::cout << std::endl;
v5.resize(3);
std::cout << "v5: ";
for (size_t i = 0; i < v5.size(); ++i) {
std::cout << v5[i] << " ";
}
std::cout << std::endl;
v5.clear();
std::cout << "v5: ";
for (size_t i = 0; i < v5.size(); ++i) {
std::cout << v5[i] << " ";
}
std::cout << std::endl;
return 0;
}
打印的结果如下:
v: 1 2 3
v2: 1 2 3
v3: 1 2 3
v4: 1 2 3
v5: 1 2 3
v5: 1 2 3 0 0
v5: 1 2 3
v5:
emplace_back函数可以用于在vector的末尾直接构造一个元素,而不需要先创建一个临时对象再将其拷贝或移动到vector中。
这个实现使用了 C++11 中的变长模板参数和完美转发,可以接受任意数量和类型的参数,并将它们转发给 T 类型的构造函数。
在实现中,我们首先检查 vector 是否已经满了,如果是,则调用 reserve 函数来扩展 vector 的容量。然后,我们使用 placement new 在 vector 的末尾直接构造一个元素,而不需要先创建一个临时对象再将其拷贝或移动到 vector 中。最后,我们将 vector 的大小加一。
需要注意的是,使用 placement new 构造对象时,需要将对象的地址作为第一个参数传递给 new 运算符,这样才能在指定的地址上构造对象
在这个实现中,我们使用了完美转发来将 push_back 函数优化成一个函数。我们还实现了 resize 函数来调整 vector 的大小,并使用了移动构造和拷贝构造函数来实现对象的拷贝和移动。我们还实现了 swap 函数来交换两个 vector 对象的内容。 在 main 函数中,我们创建了几个 vector 对象,并测试了它们的各种函数。我们可以看到,这个 vector 类的实现可以正确地处理对象的拷贝和移动,并且可以动态调整 vector 的大小。
No comments yet.