#include <iostream>
#include <cstdint>
using namespace std;
class SensorBuffer {
private:
uint8_t* data;
int size;
public:
// Constructor
SensorBuffer(int n) : data(new uint8_t[n]), size(n) {}
// Move constructor
SensorBuffer(SensorBuffer&& other) noexcept
: data(other.data), size(other.size) {
// Leave source object in a safe, empty state
other.data = nullptr;
other.size = 0;
}
// Destructor
~SensorBuffer() {
delete[] data;
}
void set(int index, uint8_t value) {
data[index] = value;
}
void print() const {
if (data == nullptr || size == 0) {
cout << "No data";
} else {
for (int i = 0; i < size; i++) {
cout << (int)data[i];
if (i != size - 1) cout << " ";
}
}
cout << endl;
}
};
int main() {
int N;
cin >> N;
SensorBuffer A(N);
for (int i = 0; i < N; i++) {
int temp;
cin >> temp;
A.set(i, static_cast<uint8_t>(temp));
}
// Move construction
SensorBuffer B = std::move(A);
A.print(); // Expected: No data
B.print(); // Expected: original data
return 0;
}
Explanation & Logic Summary:
The move constructor transfers ownership of the dynamically allocated buffer by copying the raw pointer and size from the source object to the destination object. The source object is then reset by setting its pointer to nullptr and its size to zero.
This guarantees:
Firmware Relevance & Real-World Context:
Move semantics are essential in embedded and firmware development for:
Using move semantics instead of copying reduces RAM usage, minimizes CPU cycles, and improves throughput on constrained embedded hardware.
Input
1 42
Expected Output
No data 42