Beispiellösung
Content |
#ifndef ARRAY_HPP #define ARRAY_HPP #include <algorithm> #include <cassert> #include <cstdlib> #include <new> #include <utility> template<typename T> class Array { public: Array() : size(0), data(nullptr) { } Array(std::size_t size) : size(size), data(size > 0? static_cast<T*>(operator new(sizeof(T) * size)) : nullptr) { for (std::size_t index = 0; index < size; ++index) { new (data + index) T(); } } Array(std::size_t size, const T& t) : size(size), data(size > 0? static_cast<T*>(operator new(sizeof(T) * size)) : nullptr) { for (std::size_t index = 0; index < size; ++index) { new (data + index) T(t); } } Array(const Array& other) : size(other.size), data(size > 0? static_cast<T*>(operator new(sizeof(T) * size)) : nullptr) { for (std::size_t index = 0; index < size; ++index) { new (data + index) T(other.data[index]); } } friend void swap(Array& a1, Array& a2) { using std::swap; swap(a1.size, a2.size); swap(a1.data, a2.data); } Array(Array&& other) : Array() { swap(*this, other); } ~Array() { for (std::size_t index = 0; index < size; ++index) { data[index].~T(); } operator delete(data); } Array& operator=(Array other) { swap(*this, other); return *this; } std::size_t get_size() const { return size; } T& operator()(std::size_t index) { assert(index < size); return data[index]; } const T& operator()(std::size_t index) const { assert(index < size); return data[index]; } private: std::size_t size; T* data; }; #endif
#include <iostream> #include "array.hpp" int main() { Array<Array<double>> m(8); for (std::size_t i = 0; i < m.get_size(); ++i) { m(i) = Array<double>(m.get_size()); for (std::size_t j = 0; j < m(i).get_size(); ++j) { m(i)(j) = i + j; } } for (std::size_t i = 0; i < m.get_size(); ++i) { for (std::size_t j = 0; j < m(i).get_size(); ++j) { std::cout << " " << m(i)(j); } std::cout << std::endl; } }
theon$ g++ -Wall -o test-array test-array.cpp theon$ valgrind ./test-array ==2039== Memcheck, a memory error detector ==2039== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==2039== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==2039== Command: ./test-array ==2039== 0 1 2 3 4 5 6 7 1 2 3 4 5 6 7 8 2 3 4 5 6 7 8 9 3 4 5 6 7 8 9 10 4 5 6 7 8 9 10 11 5 6 7 8 9 10 11 12 6 7 8 9 10 11 12 13 7 8 9 10 11 12 13 14 ==2039== ==2039== HEAP SUMMARY: ==2039== in use at exit: 5,128 bytes in 1 blocks ==2039== total heap usage: 11 allocs, 10 frees, 78,472 bytes allocated ==2039== ==2039== LEAK SUMMARY: ==2039== definitely lost: 0 bytes in 0 blocks ==2039== indirectly lost: 0 bytes in 0 blocks ==2039== possibly lost: 5,128 bytes in 1 blocks ==2039== still reachable: 0 bytes in 0 blocks ==2039== suppressed: 0 bytes in 0 blocks ==2039== Rerun with --leak-check=full to see details of leaked memory ==2039== ==2039== For counts of detected and suppressed errors, rerun with: -v ==2039== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) theon$
Und hier der Test zum zweiten Teil der Aufgabe:
#include "array.hpp" struct Test { Test(int i) : i(i) { } int i; }; int main() { Array<Test> t(10, Test(42)); }
theon$ g++ -Wall -o test1 test1.cpp theon$ valgrind ./test1 ==2063== Memcheck, a memory error detector ==2063== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==2063== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==2063== Command: ./test1 ==2063== ==2063== ==2063== HEAP SUMMARY: ==2063== in use at exit: 0 bytes in 0 blocks ==2063== total heap usage: 2 allocs, 2 frees, 72,744 bytes allocated ==2063== ==2063== All heap blocks were freed -- no leaks are possible ==2063== ==2063== For counts of detected and suppressed errors, rerun with: -v ==2063== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) theon$