Random access to array of raw buffers of different sizes? - c++

I have an array of array: struct chunk { char * data; size_t size; }; chunk * chunks;. The data size in each chunk is dynamic and differ between chunks. Linear access to data is easy with a nested for loop:
for (chunk * chunk_it = chunks; chunk_it != chunks + count; ++chunk_it) {
for (char * it = chunk_it->data; it != chunk_it->data + chunk_it->size; ++it) {
/* use it here */
}
}
I want to turn this into random access to chunks->data using operator[] as an interface, spanning multiple chunks.
It works by linearly searching for the right chunk, then just calculating the offset of the data I want.
template <class T>
void random_access(int n) {
chunk * c;
for (int i = 0; i < count; ++i) {
c = chunks + i;
size_t size = c->size;
if (n - size < 0) {
n -= size; // mutate n to fit into current chunk
} else {
break; // found
}
}
T * data = reinterpret_cast<T *>(c->data + n);
// use data here
}
Is there a more efficient way to do this? It would be crazy to do this every time I need a T from chunks. I plan on iterating over all chunk data linearly, but I want to use the data outside of the function, and thus need to return it at the inner loop (hence why I want to turn it inside out). I also thought of using a function pointer at the inner loop, but rather not as just doing chunk_iterator[n] is much nicer.

I understand your data structure is more complicated but could you not do something like this?
I build a contiguous block of the chunk data and record the position and size of each one in the chunks array:
class chunk_manager
{
struct chunk
{
std::size_t position;
std::size_t size;
chunk(std::size_t position, std::size_t size)
: position(position), size(size) {}
};
public:
void add_chunk(std::string const& chunk)
{
m_chunks.emplace_back(m_data.size(), chunk.size());
m_data.append(chunk);
}
char* random_access(std::size_t n) { return &m_data[n]; }
std::size_t size_in_bytes() const { return m_data.size(); }
private:
std::vector<chunk> m_chunks;
std::string m_data;
};
int main()
{
chunk_manager cm;
cm.add_chunk("abc");
cm.add_chunk("def");
cm.add_chunk("ghi");
for(auto n = 0ULL; n < cm.size_in_bytes(); ++n)
std::cout << cm.random_access(n) << '\n';
}

Related

Arrays with unknown size on Arduino

I'm doing an Arduino project and I need to pass arrays with different sizes as parameter to my function.
The problem is that std::vector is not an option.
How can I do that?
The fallback is to pass a pointer to the first element in the array and the size:
void foo(int* arr, size_t size);
The reason for std::vector not being available on some platforms is that on some platforms dynamic allocations is a bad idea. However, once you are dynamically allocating arrays:
int* x = new int[42];
foo(arr,42); // array decays to pointer
delete[] x;
then you could as well use std::vector.
If std::vector is not available to you, then either search for an alternative (maybe this?) or write your own. The pointer + size approach is fragile and not recommended unless absolutely necessary. The power of std::vector is from the abstract concept to encapsulate the array, its size and capacity. Nobody can prevent you to apply that concept even if you cannot use std::vector.
In case you are talking about statically sized arrays, then thats not quite the use case for std::vector. You do not need dynamic allocation, and you can pass arrays by reference. I won't repeat here what you can find in this answer (std::array) or here (c-arrays).
Something like this should work
template<size_t N>
void DaFunction(std::array<int, N>& daArray)
you can do it without having to deal with memory allocation or pointers just by creating a string variable and a limited size array and then you start shifting
#include <Arduino.h>
class ArrayShifter
{
private:
// String Reservoire Tank
String _text;
// a fixed size array of 5 in my case (depending on the amount of data you expect)
String _viewPortArray[5];
int _size = 0;
// Methode to fill the array
bool shiftArray(int position);
public:
ArrayShifter(/* args */);
// Method that gets the text from Serial
String getSerialText();
// get data from the array
String getArrayData(int index);
// array size getter
int getSize();
//clear the array
void clearArray();
//remove item
void removeArrayItem(int index);
};
ArrayShifter::ArrayShifter(/* args */)
{
}
String ArrayShifter::getSerialText()
{
// lesteing to the serial and returning the value
_text = Serial.readString();
return _text;
}
bool ArrayShifter::shiftArray(int position)
{
/*Assuming that the data is comming separated with ";" for each row and ":" for each value
to optimize the size of array in this way :
name:value;age:value;gender:value;
*/
String text = getSerialText();
int index = 0;
_size = 0;
if (text.length() > 0) // text isn't empty
{
if (position <= 5) // if the data belongs to the first 5 range
{
for (int i = 0; i < 5; i++)
{
// get the index of our separator that we've chosed to be ";"
index = text.indexOf(";");
if (index > 0)
{
// index found
_size++;
// putting the value before ";" in the array
_viewPortArray[i] = text.substring(0, index);
// deleting the value from the tank
text = text.substring(index + 1);
}
}
}
else
{
_size = 0;
// to wich range the desired index belongs
unsigned int dataRange = ((position - position % 5));
int ghostIndex = 0;
// looping throught all ";" to get indexes
for (int i = 0; i < dataRange; i++)
{
ghostIndex = text.indexOf(";");
if (ghostIndex > 0)
{
_size++;
text = text.substring(ghostIndex + 1);
}
}
// grabing just 5 of the data
for (int i = 0; i < 5; i++)
{
if (ghostIndex > 0)
{
_size++;
_viewPortArray[i] = text.substring(0, ghostIndex);
text = text.substring(ghostIndex + 1);
}
// updating ghost index
ghostIndex = text.indexOf(';');
}
}
return true;
}
return false;
}
String ArrayShifter::getArrayData(int index)
{
// turn the roulette
if (shiftArray(index))
{
if (index <= 5)
{
// yes we have this
return _viewPortArray[index];
}
else
{
// but we have to put it in the range of 5
index = index - 5;
return _viewPortArray[index];
}
}
}
int ArrayShifter::getSize()
{
return _size;
}
void ArrayShifter::clearArray()
{
for(int i = 0 ; i <5 ; i ++)
{
_viewPortArray->remove(i);
_size = 0;
}
}
void ArrayShifter::removeArrayItem(int index)
{
_viewPortArray->remove(index);
_size--;
}
main class :
#include <Arduino.h>
#include <ArrayShifter.h>
ArrayShifter array;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while (!Serial){}
}
void loop() {
if(Serial.available()>0)
{
Serial.println(array.getArrayData(7));
int sizeOption2 = array.getSize();
Serial.println(sizeOption2);
array.removeArrayItem(7);
Serial.println(array.getArrayData(7));
}
}
please check my github repository
https://github.com/Riadam/ViewPort-Array-Shifter-for-Arduino-Uno.git

Improve Time Efficiency of Driver Program

Sorry that the title is vague. Essentially I am trying to approve the time (and overall) efficiency of a C++ driver program which:
Reads in a file line by line using ifstream
It is vital to my program that the lines are processed seperately, so I currently have 4 seperate calls to getline.
The program reads the string line into a vector of integers using string-stream.
Finally, it converts the vector into to a linked list of integers. Is there a way or a function that can directly read the integers from the file into the ll of integers?
Here is the driver code:
int main(int argc, char *argv[])
{
ifstream infile(argv[1]);
vector<int> vals_add;
vector<int> vals_remove;
//Driver Code
if(infile.is_open()){
string line;
int n;
getline(infile, line);
istringstream iss (line);
getline(infile, line);
istringstream iss2 (line);
while (iss2 >> n){
vals_add.push_back(n);
}
getline(infile, line);
istringstream iss3 (line);
getline(infile, line);
istringstream iss4 (line);
while (iss4 >> n){
vals_remove.push_back(n);
}
int array_add[vals_add.size()];
copy(vals_add.begin(), vals_add.end(), array_add);
int array_remove[vals_remove.size()];
copy(vals_remove.begin(), vals_remove.end(), array_remove);
Node *ptr = CnvrtVectoList(array_add, sizeof(array_add)/sizeof(int));
print(ptr);
cout << "\n";
for(int i = 0; i < vals_remove.size(); i++){
deleteNode(&ptr, vals_remove[i]);
}
print(ptr);
cout << "\n";
}
Here is a small example input:
7
6 18 5 20 48 2 97
8
3 6 9 12 28 5 7 10
Where lines 2 and 4 MUST be processed as separate lists, and lines 1 and 3 are the size of the lists (they must dynamically allocate memory so the size must remain exact to the input).
There are multiple points that can be improved.
First off, remove unnecessary code: you’re not using iss and iss3. Next, your array_add and array_remove seem to be redundant. Use the vectors directly.
If you have a rough idea of how many values you’ll read on average, reserve space in the vectors to avoid repeated resizing and copying (actually you seem to have these numbers in your input; use this information instead of throwing it away!). You can also replace your while reading loops with std::copy and std::istream_iterators.
You haven’t shown how CnvrtVectoList is implemented but in general linked lists aren’t particularly efficient to work with due to lack of locality: they throw data all over the heap. Contiguous containers (= vectors) are almost always more efficient, even when you need to remove elements in the middle. Try using a vector instead and time the performance carefully.
Lastly, can you sort the values? If so, then you can implement the deletion of values a lot more efficiently using iterative calls to std::lower_bound, or a single call to std::set_difference.
If (and only if!) the overhead is actually in the reading of the numbers from a file, restructure your IO code and don’t read lines separately (that way you’ll avoid many redundant allocations). Instead, scan directly through the input file (optionally using a buffer or memory mapping) and manually keep track of how many newline characters you’ve encountered. You can then use the strtod family of functions to scan numbers from the input read buffer.
Or, if you can assume that the input is correct, you can avoid reading separate lines by using the information provided in the file:
int add_num;
infile >> add_num;
std::copy_n(std::istream_iterator<int>(infile), std::inserter(your_list, std::end(your_list));
int del_num;
infile >> del_num;
std::vector<int> to_delete(del_num);
std::copy_n(std::istream_iterator<int>(infile), del_num, to_delete.begin());
for (auto const n : del_num) {
deleteNode(&ptr, n);
}
First of all: why do you use some custom list data structure? It's very likely that it is half-baked, i.e. doesn't have support for allocators, and thus would be much harder to adapt to perform well. Just use std::list for a doubly-linked list, or std::forward_list for a singly-linked list. Easy.
There are several requirements that you seem to imply:
The values of type T (for example: an int) are to be stored in a linked list - either std::list<T> or std::forward_list<T> (not a raw list of Nodes).
The data shouldn't be unnecessarily copied - i.e. the memory blocks shouldn't be reallocated.
The parsing should be parallelizable, although this makes sense only on fast data sources where the I/O won't dwarf CPU time.
The idea is then:
Use a custom allocator to carve memory in contiguous segments that can store multiple list nodes.
Parse the entire file into linked lists that uses the above allocator. The list will allocate memory segments on demand. A new list is started on each newline.
Return the 2nd and 4th list (i.e. lists of elements in the 2nd and 4th line).
It's worth noting that the lines that contain element counts are unnecessary. Of course, that data could be passed to the allocator to pre-allocate enough memory segments, but this disallows parallelization, since parallel parsers don't know where the element counts are - these get found only after the parallel-parsed data is reconciled. Yes, with a small modification, this parsing can be completely parallelized. How cool is that!
Let's start simple and minimal: parse the file to produce two lists. The example below uses a std::istringstream over the internally generated text view of the dataset, but parse could also be passed a std::ifstream of course.
// https://github.com/KubaO/stackoverflown/tree/master/questions/linked-list-allocator-58100610
#include <forward_list>
#include <iostream>
#include <sstream>
#include <vector>
using element_type = int;
template <typename allocator> using list_type = std::forward_list<element_type, allocator>;
template <typename allocator>
std::vector<list_type<allocator>> parse(std::istream &in, allocator alloc)
{
using list_t = list_type<allocator>;
std::vector<list_t> lists;
element_type el;
list_t *list = {};
do {
in >> el;
if (in.good()) {
if (!list) list = &lists.emplace_back(alloc);
list->push_front(std::move(el));
}
while (in.good()) {
int c = in.get();
if (!isspace(c)) {
in.unget();
break;
}
else if (c=='\n') list = {};
}
} while (in.good() && !in.eof());
for (auto &list : lists) list.reverse();
return lists;
}
And then, to test it:
const std::vector<std::vector<element_type>> test_data = {
{6, 18, 5, 20, 48, 2, 97},
{3, 6, 9, 12, 28, 5, 7, 10}
};
template <typename allocator = std::allocator<element_type>>
void test(const std::string &str, allocator alloc = {})
{
std::istringstream input{str};
auto lists = parse(input, alloc);
assert(lists.size() == 4);
lists.erase(lists.begin()+2); // remove the 3rd list
lists.erase(lists.begin()+0); // remove the 1st list
for (int i = 0; i < test_data.size(); i++)
assert(std::equal(test_data[i].begin(), test_data[i].end(), lists[i].begin()));
}
std::string generate_input()
{
std::stringstream s;
for (auto &data : test_data) {
s << data.size() << "\n";
for (const element_type &el : data) s << el << " ";
s << "\n";
}
return s.str();
}
Now, let's look at a custom allocator:
class segment_allocator_base
{
protected:
static constexpr size_t segment_size = 128;
using segment = std::vector<char>;
struct free_node {
free_node *next;
free_node() = delete;
free_node(const free_node &) = delete;
free_node &operator=(const free_node &) = delete;
free_node *stepped_by(size_t element_size, int n) const {
auto *p = const_cast<free_node*>(this);
return reinterpret_cast<free_node*>(reinterpret_cast<char*>(p) + (n * element_size));
}
};
struct segment_store {
size_t element_size;
free_node *free = {};
explicit segment_store(size_t element_size) : element_size(element_size) {}
std::forward_list<segment> segments;
};
template <typename T> static constexpr size_t size_for() {
constexpr size_t T_size = sizeof(T);
constexpr size_t element_align = std::max(alignof(free_node), alignof(T));
constexpr auto padding = T_size % element_align;
return T_size + padding;
}
struct pimpl {
std::vector<segment_store> stores;
template <typename T> segment_store &store_for() {
constexpr size_t element_size = size_for<T>();
for (auto &s : stores)
if (s.element_size == element_size) return s;
return stores.emplace_back(element_size);
}
};
std::shared_ptr<pimpl> dp{new pimpl};
};
template<typename T>
class segment_allocator : public segment_allocator_base
{
segment_store *d = {};
static constexpr size_t element_size = size_for<T>();
static free_node *advanced(free_node *p, int n) { return p->stepped_by(element_size, n); }
static free_node *&advance(free_node *&p, int n) { return (p = advanced(p, n)); }
void mark_free(free_node *free_start, size_t n)
{
auto *p = free_start;
for (; n; n--) p = (p->next = advanced(p, 1));
advanced(p, -1)->next = d->free;
d->free = free_start;
}
public:
using value_type = T;
using pointer = T*;
template <typename U> struct rebind {
using other = segment_allocator<U>;
};
segment_allocator() : d(&dp->store_for<T>()) {}
segment_allocator(segment_allocator &&o) = default;
segment_allocator(const segment_allocator &o) = default;
segment_allocator &operator=(const segment_allocator &o) {
dp = o.dp;
d = o.d;
return *this;
}
template <typename U> segment_allocator(const segment_allocator<U> &o) :
segment_allocator_base(o), d(&dp->store_for<T>()) {}
pointer allocate(const size_t n) {
if (n == 0) return {};
if (d->free) {
// look for a sufficiently long contiguous region
auto **base_ref = &d->free;
auto *base = *base_ref;
do {
auto *p = base;
for (auto need = n; need; need--) {
auto *const prev = p;
auto *const next = prev->next;
advance(p, 1);
if (need > 1 && next != p) {
base_ref = &(prev->next);
base = next;
break;
} else if (need == 1) {
*base_ref = next; // remove this region from the free list
return reinterpret_cast<pointer>(base);
}
}
} while (base);
}
// generate a new segment, guaranteed to contain enough space
size_t count = std::max(n, segment_size);
auto &segment = d->segments.emplace_front(count);
auto *const start = reinterpret_cast<free_node*>(segment.data());
if (count > n)
mark_free(advanced(start, n), count - n);
else
d->free = nullptr;
return reinterpret_cast<pointer>(start);
}
void deallocate(pointer ptr, std::size_t n) {
mark_free(reinterpret_cast<free_node*>(ptr), n);
}
using propagate_on_container_copy_assignment = std::true_type;
using propagate_on_container_move_assignment = std::true_type;
};
For the little test data we've got, the allocator will only allocate a segment... once!
To test:
int main()
{
auto test_input_str = generate_input();
std::cout << test_input_str << std::endl;
test(test_input_str);
test<segment_allocator<element_type>>(test_input_str);
return 0;
}
Parallelization would leverage the allocator above, starting multiple threads and in each invoking parse on its own allocator, each parser starting at a different point in the file. When the parsing is done, the allocators would have to merge their segment lists, so that they'd compare equal. At that point, the linked lists could be combined using usual methods. Other than thread startup overhead, the parallelization would have negligible overhead, and there'd be no data copying involved to combine the data post-parallelization. But I leave this exercise to the reader.

My vector works sometimes and othertimes it doesn't

I'm trying to make my own vector, but i've got the following problem: When I push_back 100 times there's no problem. When I push_back 1000 the program does not work
#include <iostream>
#include <stdlib.h>
#include <conio.h>
struct Exception {
static const char* out_of_range;
};
const char* Exception::out_of_range = "[Error]: Out of range";
template < typename T >
struct vector {
typedef T myType;
public:
vector() {
m_vector = (myType*) malloc ( sizeof( myType ) );
m_position = 0;
}
template < typename ... Ts >
vector(myType head, Ts ... tail) {
m_position = 0;
m_vector = (myType*) malloc( (sizeof ...( tail ) + 1) * sizeof( myType ) );
this->push_back(head);
(this->push_back(tail),...);
}
~vector() {
free(m_vector);
m_vector = NULL;
}
void push_back( myType value ) {
m_vector[ m_position ] = value;
++m_position;
m_vector = (myType*) realloc(m_vector, m_position * sizeof(myType));
}
void pop_back() {
--m_position;
m_vector = (myType*)realloc( m_vector, m_position * sizeof (myType) );
}
myType at( size_t pos ) {
try {
if (pos < m_position)
return m_vector[ pos ];
else throw Exception::out_of_range;
} catch (const char* e) {
printf("%s", e);
return (myType){};
}
}
inline myType& front() { return *m_vector; }
inline myType& back() { return *(m_vector + size() -1); }
inline myType* data() { return m_vector; }
inline myType* begin() { return m_vector; }
inline myType* end() { return (m_vector + size()); }
inline myType operator[](size_t pos) { return m_vector[ pos ]; }
inline size_t size() { return m_position; }
inline bool empty () { return (begin() == end()? true:false); }
private:
myType* m_vector;
size_t m_position;
};
Here is my main that use push_back by 100 times:
int main() {
vector<int> v;
for(int i = 0; i < 100; ++i) v.push_back(i);
for(int i = 0; i < 100; ++i) std::cout << v[i];
}
And here the hunted code ahah:
int main() {
vector<int> v;
for(int i = 0; i < 1000; ++i) v.push_back(i);
for(int i = 0; i < 1000; ++i) std::cout << v[i];
}
With "doesn't work" I'm trying to say that when I have 100 values inserted by push_back the program show me all the values from 0 to 99... but when I've got 1000 values (I don't know why) the program show only a black screen and nothing more
Consider the first call of
void push_back(myType value) {
m_vector[m_position] = value; // Store into 0
++m_position; // set `m_position` to 1
m_vector = (myType*)realloc(m_vector, m_position * sizeof(myType)); // Allocate more space.
}
How much more space is allocated on that last line? m_position * sizeof(myType). This resolves to 1 * sizeof(myType). Enough space for 1 myType. In other words the same amount of space the program already had. This is not useful.
Let's look at the next push_back
void push_back(myType value) {
m_vector[m_position] = value; // Store into 1. There is no 1. Program now broken
++m_position; // set `m_position` to 2
m_vector = (myType*)realloc(m_vector, m_position * sizeof(myType)); // Allocate more space.
}
The next push_back writes into invalid storage. Program now officially broken and no further point debugging.
How do we fix this?
Let's ignore the fact that malloc and family don't handle complex data structures and vector does not observe the Rules of Three and Five. Those are best handled in other questions. How do we fix this with realloc?
m_vector = (myType*) realloc(m_vector, (m_position +1) * sizeof(myType));
smooths over the immediate rough spot. But this is inefficient as hell. Every addition triggers a realloc. This really, really hurts performance. Aggregate O(1) goes right out the window replaced by O(n), copy every time, plus a potentially very expensive memory allocation.1
Worse, what happens when you remove an item? You lose track of how much was in the vector and may find yourself reallocing smaller buffers. Yuck.
To do this right, first add a m_capacity member to track how much data can be stored so that we don't have to reallocate if the amount needed is less than the amount required.
Then we test for amount of space and possibly reallocate before trying to store.
void push_back( myType value ) {
if (m_position >= m_capacity)
{ // need to reallocate
m_capacity *= 2;
myType * temp = (myType*) realloc(m_vector, m_capacity *sizeof(myType));
// ask for more than is needed. Reduce number of reallocations needed
// do not overwrite m_vector. realloc can fail to allocate and then where are you?
if (temp != NULL)
{
m_vector = temp;
}
else
{
// handle error. Probably throw exception. Definitely exit function
// before trying to add new element
}
}
m_vector[ m_position ] = value; // now guarantied to have space.
++m_position;
}
1This isn't strictly true. One of the things you'll find is that memory provided often isn't as granular as what you asked for. When the program asks for X bytes, it might get a convenient block of free memory larger than X bytes. You ever noticed that sometimes you can run off the end of a buffer and the program doesn't notice and immediately crash? This extra space is one of the reasons. Quite often realloc can take advantage of this and keep using the same allocation over and over, allowing the program to legally see more of it. You can't count on this, though.
I assume the idea behind your code is that m_vector should always be able to hold one more value than it currently does. Your push_back funtion is wrong then, it should realloc for m_position + 1.

Resetting array using indices

I have an array whose size and values keep changing during execution all the time.
I want to do that with minimum possible performance overhead.
Instead ochanging array size I simply have member int variables indicating start and end Index and I expect consumer of this array to use these indices in the foor loop. The risk is, if the consumer does not use the start and endindex it may end up causing error. Is there a better way of doing that?
So what I have is:
MyClass
{
public:
BusinessClass myArray[MAX_COUNT];//the array
int StartIndex; //start index
int EndIndex; //End index
Logic()
{
//modified the array and changes start and end index
}
}
MyConsumer
{
MyClass obj;
public:
void ReadArray()
{
for (int i = obj.StartIndex ; i <obj.EndIndex; i++)
{
//perform logic
}
}
}
Instead of exposing the underlying array, you could have a length method that returns EndIndex-StartIndex, and an array operator that returns an item from the array offset by the value of the StartIndex.
The you would access the items in the array like this:
for (int i = 0; i < obj.length(); i++) {
BusinessClass &item = obj[i];
}
The MyClass class would look something like this:
class MyClass {
public:
size_t length() const {
return EndIndex - StartIndex;
};
BusinessClass &operator[](size_t off) {
return myArray[StartIndex+off];
};
private:
BusinessClass myArray[MAX_COUNT];
int StartIndex; //start index
int EndIndex; //End index
};

dynamic memory allocation with arrays in c++

I am trying to insert an int into an array that is in a class object, and I cannot figure out what I am doing wrong. The current state of my code never inserts the int into the array.
Basically what I am trying to do is when i call insert(int) it will check to to see if there is any room left in the array, and if there is it will add it, otherwise it would reallocate with 8 more spaces in the array.
here is some relevant class info
private:
unsigned Cap; // Current capacity of the set
unsigned Num; // Current count of items in the set
int * Pool; // Pointer to array holding the items
public:
// Return information about the set
//
bool is_empty() const { return Num == 0; }
unsigned size() const { return Num; }
unsigned capacity() const { return Cap; }
// Initialize the set to empty
//
Set()
{
Cap = Num = 0;
Pool = NULL;
}
here is the code i am working on
bool Set::insert(int X)
{
bool Flag = false;
if (Num == Cap)
{
//reallocate
const unsigned Inc = 8;
int * Temp = new int[Cap+Inc];
for (unsigned J=0;J<Num;J++)
{
Temp[J] = Pool[J];
}
delete [] Pool;
Pool = Temp;
Cap = Cap+Inc;
}
if(Num < Cap)
{
Pool[Num+1] = X;
Flag = true;
}
return Flag;
}
Your insert function never updates Num. Try Pool[Num++] = X; or something like that.
You probably want to increment the number of element but only after copying the new element in: the first element should have index 0. Basically, your insert() function should look something like this:
bool Set::insert(int X)
{
if (Num == Cap)
{
const unsigned Inc(std::max(8, 2 * Cap));
std::unique_ptr<int[]> Temp(new int[Cap+Inc]);
std::copy(Pool.get(), Pool.get() + Num, Temp.get());
Pool.swap(Temp);
Cap += Inc;
}
Pool[Num] = X;
++Num;
return true;
}
Of course, this assumes that Pool is reasonably declared as std::unique_ptr<int[]> (or something with similar functionality which is easy to write if necessary). The reason to use std::unique_ptr<int[]> rather than raw pointers is that they automatically clean up resources when they are destroyed. Copying a sequence of ints won't throw an exception but if int get's replaced by a std::string or a template parameters there is potential to throw exceptions.