// Copyright 2026, University of Freiburg,
// Chair of Algorithms and Data Structures
// Author: Hannah Bast <bast@cs.uni-freiburg.de>
#include <cstdio>
#include <cstdlib>
#include <locale.h>
// Class for objects that manage their own piece of memory.
class ObjectWithAllocatedMemory {
public:
// Construct with given number of bytes.
explicit ObjectWithAllocatedMemory(size_t size) {
bytes_ = new char[size];
size_ = size;
id_ = nextId_++;
printf("Constructor for object #%d (size = %3zu, address = %'zu)\n", id_,
size_, (size_t)bytes_);
}
// Copy constructor.
ObjectWithAllocatedMemory(const ObjectWithAllocatedMemory &other) {
// bytes_ = other.bytes_;
bytes_ = new char[other.size_];
for (size_t i = 0; i < other.size_; i++) {
bytes_[i] = other.bytes_[i];
}
size_ = other.size_;
id_ = nextId_++;
printf("Copy constr for object #%d (size = %3zu, address = %'zu)\n", id_,
size_, (size_t)bytes_);
}
// Copy assignment operator.
//
// NOTE: This does NOT create a new object, but overwrite the object.
ObjectWithAllocatedMemory &operator=(const ObjectWithAllocatedMemory &other) {
delete[] bytes_;
bytes_ = new char[other.size_];
for (size_t i = 0; i < other.size_; i++) {
bytes_[i] = other.bytes_[i];
}
size_ = other.size_;
printf("Copy assign for object #%d (size = %3zu, address = %'zu)\n", id_,
size_, (size_t)bytes_);
// This will be explained later or in V7.
return *this;
}
// Destructor.
~ObjectWithAllocatedMemory() {
delete[] bytes_;
printf("Destructor for object #%d (size = %3zu, address = %'zu)\n", id_,
size_, (size_t)bytes_);
}
// Get the size.
size_t size() const { return size_; }
private:
// The bytes managed by this object.
char *bytes_;
// The number of bytes managed by this object.
size_t size_;
// The ID of this object.
int id_;
// The next ID for an object of this class.
static int nextId_;
};
// The first ID of `ObjectWithAllocatedMemory` objects is 1.
int ObjectWithAllocatedMemory::nextId_ = 1;
// Function that does something with an `ObjectWithAllocatedMemory` object.
void doSomething(const ObjectWithAllocatedMemory &object) {
printf("Size matters: %zu\n", object.size());
}
// Demonstrating stuff related to dynamic memory allocation for Vorlesung 6.
int main(int argc, char *argv[]) {
// Set locale for thousand separators in `printf`.
setlocale(LC_NUMERIC, "");
// Create object that allocates 137 bytes for itself.
ObjectWithAllocatedMemory object1(137);
// Create another object that is copy of `object1`.
ObjectWithAllocatedMemory object2(object1);
// Assign one object to another.
ObjectWithAllocatedMemory object3(42);
object1 = object3;
// Equivalent to: object1.operator=(object3);
// Is this copy constructor (yes!) or copy assignment?
ObjectWithAllocatedMemory object4 = object1;
printf("\n");
// doSomething(object3);
// doSomething(1757);
doSomething(ObjectWithAllocatedMemory(1757));
// Equivalent to: doSomething(ObjectWithAllocatedMemory(1757));
printf("\n");
// // Parse command line arguments.
// if (argc != 2) {
// printf("Usage: ./DynamicAllocationMain <number>\n");
// return 1;
// }
// const size_t n = atoi(argv[1]);
// // Allocate n bytes and free them again.
// // char bytes[n];
// char *bytes = new char[n];
// bytes[17] = 0;
// delete[] bytes;
// // delete[] bytes;
}