Beispiellösung
Content |
#ifndef INTEGER_SEQUENCE_HPP #define INTEGER_SEQUENCE_HPP #include <cassert> #include <cstdlib> #include <new> #include <iostream> class IntegerSequence { public: IntegerSequence() : data{nullptr}, size{0}, allocated{0} { std::cout << "IntegerSequence: default constructor" << std::endl; } IntegerSequence(const IntegerSequence& other) : data{ other.data? static_cast<int*>(std::malloc(other.allocated * sizeof(int))) : nullptr }, size{other.size}, allocated{other.allocated} { if (size > 0 && !data) { throw std::bad_alloc(); } for (std::size_t i = 0; i < size; ++i) { data[i] = other.data[i]; } std::cout << "IntegerSequence: copy constructor copying " << size << " elements" << std::endl; } IntegerSequence(IntegerSequence&& other) : data{other.data}, size{other.size}, allocated{other.allocated} { other.data = nullptr; other.size = 0; other.allocated = 0; std::cout << "IntegerSequence: move constructor moving " << size << " elements" << std::endl; } ~IntegerSequence() { std::cout << "IntegerSequence: destructor deleting " << size << " elements" << std::endl; std::free(data); } IntegerSequence& operator=(const IntegerSequence& other) { if (other.size > allocated) { int* newdata = static_cast<int*>(std::realloc(data, other.allocated * sizeof(int))); if (!newdata) { throw std::bad_alloc(); } data = newdata; allocated = other.allocated; } size = other.size; for (std::size_t i = 0; i < size; ++i) { data[i] = other.data[i]; } std::cout << "IntegerSequence: assignment operator copying " << size << " elements" << std::endl; return *this; } IntegerSequence& operator=(IntegerSequence&& other) { std::swap(data, other.data); std::swap(size, other.size); std::swap(allocated, other.allocated); std::cout << "IntegerSequence: move assignment taking " << size << " elements" << std::endl; return *this; } void add(int value) { if (size == allocated) { std::size_t newsize = allocated * 2 + 8; int* newdata = static_cast<int*>(std::realloc(data, newsize * sizeof(int))); if (!newdata) { throw std::bad_alloc(); } data = newdata; allocated = newsize; } data[size++] = value; } std::size_t length() const { return size; } int& operator()(std::size_t index) { assert(index < size); return data[index]; } const int& operator()(std::size_t index) const { assert(index < size); return data[index]; } private: int* data; std::size_t size; std::size_t allocated; }; #endif
#include <cstdlib> #include <iostream> #include "IntegerSequence.hpp" void print(const IntegerSequence& is) { for (std::size_t i = 0; i < is.length(); ++i) { std::cout << " " << is(i); } std::cout << std::endl; } IntegerSequence gen_sequence(IntegerSequence seq, int val) { for (int i = 1; i <= val; ++i) { seq.add(i); } return seq; } int main() { IntegerSequence iseq; // default constructor iseq.add(1); IntegerSequence iseq2{iseq}; // copy constructor iseq2.add(2); iseq = iseq2; // regular assignment operator std::cout << "iseq: "; print(iseq); IntegerSequence iseq3 = gen_sequence(iseq, 3); // move constructor std::cout << "iseq3: "; print(iseq3); IntegerSequence iseq4; iseq4 = gen_sequence(iseq, 3); // move assignment std::cout << "iseq4: "; print(iseq4); }
theon$ g++ -Wall -o test_is test_is.cpp theon$ valgrind ./test_is ==1818== Memcheck, a memory error detector ==1818== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==1818== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==1818== Command: ./test_is ==1818== IntegerSequence: default constructor IntegerSequence: copy constructor copying 1 elements IntegerSequence: assignment operator copying 2 elements iseq: 1 2 IntegerSequence: copy constructor copying 2 elements IntegerSequence: move constructor moving 5 elements IntegerSequence: destructor deleting 0 elements iseq3: 1 2 1 2 3 IntegerSequence: default constructor IntegerSequence: copy constructor copying 2 elements IntegerSequence: move constructor moving 5 elements IntegerSequence: move assignment taking 5 elements IntegerSequence: destructor deleting 0 elements IntegerSequence: destructor deleting 0 elements iseq4: 1 2 1 2 3 IntegerSequence: destructor deleting 5 elements IntegerSequence: destructor deleting 5 elements IntegerSequence: destructor deleting 2 elements IntegerSequence: destructor deleting 2 elements ==1818== ==1818== HEAP SUMMARY: ==1818== in use at exit: 5,128 bytes in 1 blocks ==1818== total heap usage: 6 allocs, 5 frees, 77,960 bytes allocated ==1818== ==1818== LEAK SUMMARY: ==1818== definitely lost: 0 bytes in 0 blocks ==1818== indirectly lost: 0 bytes in 0 blocks ==1818== possibly lost: 5,128 bytes in 1 blocks ==1818== still reachable: 0 bytes in 0 blocks ==1818== suppressed: 0 bytes in 0 blocks ==1818== Rerun with --leak-check=full to see details of leaked memory ==1818== ==1818== For counts of detected and suppressed errors, rerun with: -v ==1818== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) theon$