#include <algorithm> // std::copy, std::fill
#include <memory> // std::move
class DynamicIntArray {
size_t size;
int *data;
public:
explicit DynamicIntArray(size_t size, int initial_value)
: size(size), data(new int[size]) {
std::fill(data, &data[size], initial_value);
}
~DynamicIntArray() {
delete[] data;
size = 0;
}
// Copy constructor (copies object)
DynamicIntArray(DynamicIntArray const &other)
: size(other.size), data(new int[other.size]) {
std::copy(other.data, &other.data[size], data);
}
// Move constructor ("steals" data, no allocation or copy necessary)
DynamicIntArray(DynamicIntArray &&other) noexcept
: size(other.size), data(other.data) {
// Ensure that the moved-from object `other` can be safely destroyed (using
// the destructor that calls to delete[]).
other.data = nullptr;
other.size = 0;
}
//
// Copy- and move-assignment operators are invoked, if _this_ object has
// already been constructed.
//
// Copy-assignment operator (copies object)
DynamicIntArray &operator=(DynamicIntArray const &other) {
// If the number of elements are equal, we can re-use the existing memory.
if (size == other.size) {
std::copy(other.data, &other.data[other.size], data);
return *this;
}
// Otherwise, we need to clean-up and re-allocate the required amount of
// memory.
delete[] data;
data = new int[other.size];
size = other.size;
std::copy(other.data, &other.data[size], data);
return *this;
}
// Move-assignment operator ("steals" data, no allocation or copy necessary)
DynamicIntArray &operator=(DynamicIntArray &&other) noexcept {
delete[] data; // Clean-up our own data before we "steal" from `other`.
data = other.data;
size = other.size;
// Ensure that the moved-from object `other` can be safely destroyed (using
// the destructor that calls to delete[]).
other.data = nullptr;
other.size = 0;
return *this;
}
int &getValueAt(size_t idx) { return data[idx]; }
};
int main() {
DynamicIntArray a{/*size=*/128, /*initial_value=*/42};
DynamicIntArray b = a; // Copy constructor.
DynamicIntArray c = std::move(b); // Move constructor.
// Construct two more objects.
DynamicIntArray d{/*size=*/4, /*initial_value=*/0};
DynamicIntArray e{/*size=*/8, /*initial_value=*/9001};
// Use the assignment operators.
a = d; // Copy-assignment operator.
c = std::move(e); // Move-assignment operator.
int i = b.getValueAt(0); // Noncompliant: `b` has been moved-from during construction of `c`.
int j = e.getValueAt(0); // Noncompliant: `e` has been moved-from during move-assignment to `c`.
return i + j;
}
Use either the
// … or /* … */
comment syntax, but be consistent and do not mix them within the same file.