Beispiellösung

Content

#ifndef INTEGER_SEQUENCE_HPP
#define INTEGER_SEQUENCE_HPP

#include <cassert>
#include <cstdlib>
#include <new>

class IntegerSequence {
   public:
      IntegerSequence() : data(nullptr), size(0), allocated(0) {
      }
      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];
	 }
      }
      ~IntegerSequence() {
	 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];
	 }
	 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 <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;
}

int main() {
   IntegerSequence iseq;
   int value;
   while (std::cin >> value) {
      iseq.add(value);
   }
   std::cout << "iseq: "; print(iseq);
   IntegerSequence iseq2 = iseq; // copy constructor
   iseq2.add(42);
   std::cout << "iseq2: "; print(iseq2);
   iseq = iseq2; // copy it back
   std::cout << "iseq: "; print(iseq);
}
theon$ g++ -Wall -o test_is test_is.cpp
theon$ echo 1 2 3 4 5 6 7 8 | valgrind ./test_is
==22592== Memcheck, a memory error detector
==22592== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==22592== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==22592== Command: ./test_is
==22592== 
--22592-- WARNING: Serious error when reading debug info
--22592-- When reading debug info from /lib/amd64/ld.so.1:
--22592-- Can't make sense of .data section mapping
iseq:  1 2 3 4 5 6 7 8
iseq2:  1 2 3 4 5 6 7 8 42
iseq:  1 2 3 4 5 6 7 8 42
==22592== 
==22592== HEAP SUMMARY:
==22592==     in use at exit: 10,256 bytes in 2 blocks
==22592==   total heap usage: 7 allocs, 5 frees, 83,216 bytes allocated
==22592== 
==22592== LEAK SUMMARY:
==22592==    definitely lost: 0 bytes in 0 blocks
==22592==    indirectly lost: 0 bytes in 0 blocks
==22592==      possibly lost: 10,256 bytes in 2 blocks
==22592==    still reachable: 0 bytes in 0 blocks
==22592==         suppressed: 0 bytes in 0 blocks
==22592== Rerun with --leak-check=full to see details of leaked memory
==22592== 
==22592== For lists of detected and suppressed errors, rerun with: -s
==22592== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
theon$