基于动态数组的拷贝构造函数与析构函数实现问题咨询
Hey there! Let's work through this DynArray implementation together—since re-creating a basic vector is such a great way to nail down dynamic memory management in C++. I’ll cover all the core requirements you mentioned, plus the common pitfalls that trip people up.
DynArray Class First, let's outline the core components you need:
Private Member Variables
You’ll need three private members to track the array, its current element count, and total capacity:
template <typename T> class DynArray { private: T* arr; // Pointer to our dynamic array size_t size_; // Number of elements currently stored size_t capacity_;// Total space available in the array // ... rest of the class methods go here };
Note: I used a template so your DynArray works with any data type (just like std::vector). If your project doesn’t need this flexibility, replace T with a specific type like int.
Default Constructor
The default constructor needs to initialize an array with capacity 2, and set size_ to 0:
DynArray() : size_(0), capacity_(2) { arr = new T[capacity_]; }
Critical: Use new[] (not new) here—we’re allocating an array of elements, not a single object.
Push_back Method with Resizing
This is where most folks run into issues. When size_ hits capacity_, we need to double the array’s capacity, copy over existing elements, clean up the old array, then add the new element. Here’s the correct implementation:
void push_back(const T& value) { // Check if we need to resize if (size_ == capacity_) { size_t new_capacity = capacity_ * 2; T* new_arr = new T[new_capacity]; // Copy all existing elements to the new array for (size_t i = 0; i < size_; ++i) { new_arr[i] = arr[i]; } // Clean up the old array to avoid memory leaks delete[] arr; // Update our pointers and capacity arr = new_arr; capacity_ = new_capacity; } // Add the new element and increment the size arr[size_] = value; size_++; }
Common Mistakes to Avoid:
- Forgetting
delete[]: If you skip deleting the old array, you’ll leave orphaned memory (a memory leak). Always pairnew[]withdelete[]. - Mixing up
size_andcapacity_: Remember—size_is how many elements are actually in use,capacity_is how many the array can hold before resizing. - Skipping element copies: If you don’t copy the old elements over, you’ll lose all existing data when you switch to the new array.
Destructor
Don’t forget to add a destructor to clean up the dynamic array when the DynArray object goes out of scope:
~DynArray() { delete[] arr; }
Without this, every DynArray you create will leave behind memory leaks when it’s destroyed.
Bonus: Rule of Three
Since we’re managing dynamic memory, you should implement the Rule of Three to avoid shallow copy bugs:
Copy Constructor
DynArray(const DynArray& other) : size_(other.size_), capacity_(other.capacity_) { arr = new T[capacity_]; // Copy all elements from the other array for (size_t i = 0; i < size_; ++i) { arr[i] = other.arr[i]; } }
Copy Assignment Operator
DynArray& operator=(const DynArray& other) { // Avoid self-assignment (e.g., da = da) if (this != &other) { // Clean up our current array first delete[] arr; // Allocate new memory and copy elements size_ = other.size_; capacity_ = other.capacity_; arr = new T[capacity_]; for (size_t i = 0; i < size_; ++i) { arr[i] = other.arr[i]; } } return *this; }
If you’re using C++11 or later, you can add move constructors/assignment operators for better performance, but the Rule of Three is the minimum to avoid crashes and leaks.
Basic Getters and Accessors
To make your DynArray usable like vector, add these simple methods:
// Get the current number of elements size_t size() const { return size_; } // Get the total capacity size_t capacity() const { return capacity_; } // Access elements by index T& operator[](size_t index) { // You can add bounds checking here if you want (like vector::at()) return arr[index]; } // Const version for read-only access const T& operator[](size_t index) const { return arr[index]; }
Example Usage
Here’s how you’d test your DynArray:
#include <iostream> int main() { DynArray<int> da; da.push_back(10); da.push_back(20); da.push_back(30); // Triggers resize to capacity 4 da.push_back(40); da.push_back(50); // Triggers resize to capacity 8 std::cout << "Size: " << da.size() << ", Capacity: " << da.capacity() << "\n"; // Output: Size: 5, Capacity: 8 for (size_t i = 0; i < da.size(); ++i) { std::cout << da[i] << " "; } // Output: 10 20 30 40 50 return 0; }
If you share your actual code snippet, I can help debug specific issues you’re facing—but this implementation covers all the core requirements you outlined.
内容的提问来源于stack exchange,提问作者DrayneO

