Initialize new[] using copy constructor - c++

I believe this is a simple question with probably a not simple answer.
Here is the code:
template<typename T>
T* copy(T* original, int size) {
T* result = new T[size];
// At this point the default constructor of all new T objects have been called.
for(int i = 0; i < size; ++i) {
// This will call the assignment operator= on all new T objects
result[i] = original[i];
}
return result;
}
Question:
Is there a way to initialize the newly allocated memory using the copy constructor of T instead of using default constructor followed by assignment operator?
The purpose is to copy each element to its analogous element in the new array using the copy constructor of T.
I imagine there could be a way to do that by allocating memory using malloc, then calling the copy constructor for each element but I don't know how.
Here is an example solution from my imagination. If this is correct or this is the best we can get, tell me. Or propose a better solution:
template<typename T>
T* copy(T* original, int size) {
T* result = malloc(sizeof(T)*size);
// At this point the default constructor of all new T objects have been called.
for(int i = 0; i < size; ++i) {
T t(original[i]);
memcpy(result+i*sizeof(T), &t, sizeof(T));
}
return result;
}
Note: Raw pointers are being used for simplicity.
Note 2: I don't need a vector. This pattern will be used to copy the underlying data structure of more complicated objects.

You will have to allocate memory by any other means, but keep in mind that size * sizeof(T) can overflow. std::allocator takes care of this.
Use std::uninitialized_copy/std::uninitialized_copy_n to perform the copy:
template<typename T>
T* copy(T* original, int size) {
std::allocator<T> alloc;
T* result = alloc.allocate(size);
try {
std::uninitialized_copy_n(original, size, result);
} catch (...) {
alloc.deallocate(result, size);
throw;
}
return result;
}
Later you can use std::destroy/std::destroy_n to destroy them and deallocate memory:
template<typename T>
void destroy(T* ptr, int size)
{
std::destroy_n(ptr, size);
std::allocator<T>().deallocate(ptr, size);
}
This should work unless you need to be able to delete them with operator delete[] - in which case there is no solution for this.
If you are implementing a custom container, you can use template allocator like standard containers do:
template<typename T, typename Allocator = std::allocator<T>>
struct container
{
[[no_unique_address]] Allocator allocator;
...
};

For the new operator I don't think so.
But yes there is. It's called std::vector:
template<typename T>
std::vector<T> copy(T* original, int size) {
return std::vector<T>{original, original + size};
}
Because you don't follow RAII and use owning raw pointers your code is not memory leak free, so don't do that! Use C++ properly.

Related

how to work with deleted object on custom vector

I know that std vectors can work with objects that are not default constructible. However, when I try to implement a slightly modified one myself, I cant seem to make such vector.
class A
{
public:
A() = delete;
A(const int &x)
:x(x)
{}
private:
int x;
};
template <typename T, int N> //default constructor of the vector
CircularBuffer<T,N>::CircularBuffer()
{
Size = 0;
Capacity =N;
Array = new T[Capacity];
Start = 0;
End = 0;
}
template <typename T, int N>
CircularBuffer<T,N>::CircularBuffer(const CircularBuffer& rhs) //copy constructor of the vector
{
Size = rhs.Size;
Capacity = rhs.Capacity;
Array = new T[Capacity];
Start = rhs.Start;
End = rhs.End;
for(int i=0;i<Capacity;i++)
{
this->Array[i] = rhs.Array[i];
}
}
template <typename T, int N> //move constructor of the vector
CircularBuffer<T,N>::CircularBuffer(CircularBuffer&& rhs)
{
rhs.Swap(*this);
}
template <typename T, int N>
void CircularBuffer<T,N>:: Swap(CircularBuffer &source)
{
swap(Size,source.Size);
swap(Capacity,source.Capacity);
swap(Start,source.Start);
swap(End,source.End);
swap(Array,source.Array);
}
When I try to make a vector with object A,
CircularBuffer<A,3> v;
error: use of deleted function ‘A::A()’
I get this error which is obviously self explanatory. Anyone can help me solve this??
The problem is here
Array = new T[Capacity];
which default constructs T objects.
std::vector uses placement new to construct objects when they are added to the vector.
Array = (T*)operator new(sizeof(T)*Capacity);
and (when you add the new item)
new(Array + i) T(...); // placement new
where ... are the arguments you wish to pass to the constructor.
See here for more details.
The issue is with the line Array = new T[Capacity];. This needs to default-initialize all members of the array, which it cannot do without a default-constructor.
std::vector gets around it by splitting allocation and construction with its allocator. I recommend you simply use std::allocator as well. Otherwise you can use placement-new to construct the elements after allocating the required memory separately.

Convert vector to owned array without copying

A std::vector is more or less this:
class vector {
T* array;
size_t length;
size_t capacity;
public:
...
}
Is it possible to extract the array object, taking ownership of it without copying any data? In other words, so that this is a valid program with no undefined behaviour or memory leaks.
int main() {
vector<int> foo = {1, 2, 3};
int* fooArray = foo.magical_extraction_method();
delete[] fooArray;
}
To be clear, I am not looking for foo.data(), &foo[0] or similar. I want ownership of the underlying array.
Is it possible to extract the array object, taking ownership of it
No, there is no standard way to extract ownership from a std::vector. Except into another vector (using move).
delete[] fooArray;
delete[] is only allowed on a pointer returned by new[]. A std::vector never owns such pointer.
Yes, using unique_ptr with a custom deleter:
template<class T>
struct VectorDeleter {
explicit constexpr VectorDeleter(std::vector<T> v) noexcept : v{std::move(v)} {};
VectorDeleter(VectorDeleter&&) = default;
VectorDeleter& operator=(VectorDeleter const&) = delete;
std::vector<T> v;
void operator()(T* p) {
assert(p == v.data());
v.clear();
}
};
template<class T>
std::unique_ptr<T[], VectorDeleter<T>> release(std::vector<T>&& v) {
auto const p = v.data();
return std::unique_ptr<T[], VectorDeleter<T>>{p, VectorDeleter<T>{std::move(v)}};
}
Example.
There is nothing in the standard that can manage the memory of a std::vector other than the same std::vector. Mostly, this is because any number of elements from 0 to capacity() may have been constructed, and these elements only must be destructed before freeing the memory.

Can I force std::vector to leave a memory leak?

Can I force std::vector to not deallocate its memory after the vector goes out of scope?
For example, if I have
int* foo() {
std::vector<int> v(10,1); // trivial vector
return &v[0];
}
int main()
{
int* bar = foo();
std::cout << bar[5] << std::endl;
}
There is no guarantee that the values will still be accessible here.
I am currently simply doing this
int* foo() {
std::vector<int> v(10,1);
int* w = new int[10];
for (int i=0; i<10; i++) {
w[i] = v[i];
}
return w;
}
but it is a little wasteful to repopulate a whole new array. Is there a way to force std::vector to not delete its array?
Note: I am not returning the vector itself because I am interfacing c++ with python using SWIG, and ARG_OUTVIEW_ARRAY requires a raw pointer and, in fact, an intentional memory leak. I would still however like to be able to make use of vector features while constructing the data itself.
It is possible but you should never do it. Forcing a vector to leave memory leak is a terrible idea and if you need such a thing then you need to re-think your design. std::vector is a resource managing type whose one of the main goals is to ensure that we don't have a leak. Never try to break that.
Now, to answer your specific question: std::vector takes an allocator type as second template parameter which is default to std::allocator<T>. Now you can write a custom allocator that doesn't release any memory and use that with your vector. Writing a custom allocator is not very trivial work, so I'm not going to describe that here (but you can Google to find the tutorials).
If you really want to use custom allocator then you must ensure that your vector never triggers a grow operation. Cause during growing capacity the vector will move/copy data to new location and release the old memories using the allocator. If you use an allocator that leaks then during growing you not only retain the final data, but also retain the old memories which I'm sure that you don't want to retain. So make sure that you create the vector with full capacity.
The vector is desiged to prevent leaks.
But if you want to shoot yourself in the foot, it's possible. Here's how you prevent the vector from deallocating its internal array:
int *foo()
{
std::vector<int> v(10,1);
int *ret = v.data();
new (&v) std::vector<int>; // Replace `v` with an empty vector. Old storage is leaked.
return ret;
}
As the other answers say, you should never do it.
No.
Vectors are not implemented to have memory leaks, and the interface does not provide a way to create one.
You can't "steal" the memory (removing ownership of it from the vector), which is possibly a bit of a shame.
Sorry, but you are going to have to either copy (as you're doing now), or not use vector.
This is a bad idea, but possible by creating a custom allocator that does not deallocate as said in other answers.
For example : (boilerplate mostly from cppref)
#include <cstdlib>
#include <new>
#include <vector>
template <typename T>
struct LeakingAllocator
{
using value_type = T;
LeakingAllocator() = default;
template <typename U> constexpr LeakingAllocator(const LeakingAllocator<U>&) noexcept {}
T* allocate(std::size_t n)
{
if(n > std::size_t(-1) / sizeof(T)) throw std::bad_alloc(); // check for overflow
if(auto p = static_cast<T*>(std::malloc(n*sizeof(T)))) return p; // return p if malloc returns a valid object
throw std::bad_alloc(); // otherwise just throw.
}
void deallocate(T* p, std::size_t) noexcept { /*leak intentionally*/ }
};
template <typename T, typename U>
bool operator==(const LeakingAllocator<T>&, const LeakingAllocator<U>&) { return true; }
template <typename T, typename U>
bool operator!=(const LeakingAllocator<T>&, const LeakingAllocator<U>&) { return false; }
template <typename T>
using LeakingVector = std::vector<T, LeakingAllocator<T>>;
Then code like
int* ret()
{
LeakingVector<int> a;
a.resize(10);
return &a[0];
}
int main()
{
auto ptr = ret();
*ptr = 10;
std::cout << *ptr;
}
becomes valid.
Not sure but, yes.
You can create a custum allocator who do nothing when deallocate => leak
Or may be you can jsut create your vectoron the heap so it will leak anyway.
int* foo() {
std::vector<int>* v = new std::vector<int>(10,1);
return &((*v)[0]);
// no delete
}
int main()
{
int* bar = foo();
std::cout << bar[5] << std::endl;
}
No.
And you're doing it wrong. Return the vector instead so the lifetime works out:
Write your own special Python memory vector class, something like (most crudely):
template <typename T>
class python_vector
{
T* buffer_;
public:
python_vector(size_t n, const T& value) : buffer_{new T(n)}
{}
// copy, assignment, operator[](), *etc*
~python_vector()
{
// DO NOTHING!
}
}
python_vector<int> foo() {
python_vector<int> v(10,1);
// process v
return v;
}
int main()
{
python_vector<int> bar = foo(); // copy allusion will build only one python_vector here
std::cout << bar[5] << std::endl;
}
In C++ you would most probably write:
auto foo()
{
std::vector<int> v(10,1); // trivial vector
return v;
}
int main()
{
const auto bar = foo();
std::cout << bar[5] << std::endl;
}

Allocating memory in an array of objects with out calling constructors?

I want to create a simple template arraylist class but when i do something like
T* typeArray = new T[10];
this creates 10 instances of the object, calling the constructor 10 times. How can i create an empty array were i can later place objects?
It's not the preferred way of doing things in C++, but
T* my_array = (T*)malloc(10 * sizeof(T));
A solution more in line with standard C++ practice is
std::vector<T> my_vector;
my_vector.reserve(10);
Note, (as alluded to in comments) the solution with reserve differs in that without further action my_vector[5] is not valid whereas my_array[5] is. You will subsequently need something like my_vector.resize(10) in order to index it, which will construct all 10 items. You can construct them front-to-back by doing push_back(T const&) or emplace_back(Args...&& args). Only after constructed this way is [] indexing legal. As a warning, [] indexing may work even when illegal, but it is undefined behavior.
template<typename T>
struct RawMem {
alignas(T) unsigned char data[sizeof(T)];
T& get_unsafe() { return *reinterpret_cast<T*>(&data[0]); }
T const& get_unsafe() const { return *reinterpret_cast<T const*>(&data[0]); }
template<typename... Args>
void Construct( Args&&... args ) {
new (&data[0]) T( std::forward<Args>(args)... );
}
void Destroy() {
get_unsafe().~T();
}
};
RawMem<std::string>* buff = new RawMem<std::string>[10];
for (int i = 0; i < 10; ++i) {
buff[i].Construct( "bob is your uncle" );
}
for (int i = 0; i < 10; ++i) {
std::cout << buff[i].get_unsafe() << "\n";
}
for (int i = 0; i < 10; ++i) {
buff[i].Destroy();
}
delete buff;
note that you are completely in charge of handling when the destructor is called, and when it isn't, with the above pattern.
I included helper Construct and Destroy functions so you don't have to mess around with placement new and the like yourself. Similarly, get_unsafe() will let you get ahold of the T& instance when you want it.
The above uses C++11 alignas, because there is no way in C++03 to solve the problem.

Templates delete in C++ when List<List<X>>

I am trying to develop a generic List with templates. This list is compound by a Pointer array T* , an integer for getting the number of elements and some methods( find, contains...) It´s important to say that I cannot use std::library.
My problem comes when I am working with a List<List<int> > for instance.
One of the methods make a resizing of the T* pointer array, So when I have this List<List>>I create an auxpointer of a bigger size than T* and copying T content to auxpointer with a memcpy. The inner Pointers (list.T.T) are copied as pointers too, not memory duplicated, so when I delete the T* pointer and reasign T=auxpointer. I have already lost the data of that pointers in my new T.
template <typename T>
void CGenericList<T>::resize()
{
T* auxPointer = new T[this->maxElements*2];
memcpy (auxPointer,this->pointer,this->maxElements*sizeof(T));
delete[] this->pointer;
this->pointer=auxPointer;
this->maxElements=2*this->maxElements;
}
template<class T>
class CGenericList
{
public:
T* pointer;
int N;
int maxElements;
CGenericList();
CGenericList(int);
~CGenericList();
void resize();
}
Can anyone give me any tips for doing it?
The code you posted shows some problems.
T* auxPointer = new T[this->maxElements*2];
here you allocate a new array of maxElements*2 - and call the default constructor.
Which in your case probably initialises all Listelements.
memcpy (auxPointer,this->pointer,this->maxElements*sizeof(T));
After that you copy the content of your old array to the memory area of the newly allocated memory. This overwrites the pointers to the just created Listelements with the ones from the old array -> memory leak.
delete[] this->pointer;
Then you delete the array, this calls the destructors of all elements.
Which hopefully will delete their content and free their memory.
this->pointer=auxPointer;
Finally you reassign the newly created array. The pointers in the list point to the old listselements and point to not allocated memory anymore (because of the call to the destructor via delete[]).
A solution would be to implement an copy constructor for your list and call it for all
elements in your array. (DeepCopy) And of course an assignment operator, i almost forgot ;)
CGenericList(const CGenericList<T>& copy);
CGenericList<T>& operator= (const CGenericList<T>& rhs)
Probably somethig like this - be aware that this is "asis" and definitely not exceptionsafe ;)
template<class T>
class CGenericList
{
public:
T* pointer;
int N;
int maxElements;
CGenericList();
CGenericList( const CGenericList<T>& copy );
CGenericList<T>& operator=(const CGenericList<T>& rhs);
CGenericList(int);
~CGenericList();
void resize();
};
template <typename T>
void CGenericList<T>::resize()
{
T* auxPointer = new T[this->maxElements*2];
for(int i=0; i < this->maxElements; i++)
{
auxPointer[i] = this->pointer[i];
}
delete[] this->pointer;
this->pointer = auxPointer;
this->maxElements = this->maxElements*2;
}
template <typename T>
CGenericList<T>::CGenericList()
:N(0)
,maxElements(0)
{
this->pointer = new T[1];
}
template <typename T>
CGenericList<T>::CGenericList(const CGenericList<T>& copy)
:N(copy.N)
,maxElements(copy.maxElements)
{
T* temp = new T[copy.maxElements];
for(int i=0; i<N; i++ )
{
temp[i] = copy.pointer[i];
}
this->pointer = temp;
}
template <typename T>
CGenericList<T>& CGenericList<T>::operator=(const CGenericList<T>& rhs)
{
if( this != &rhs )
{
delete[] this->pointer;
this->pointer = new T[rhs.maxElements];
for(int i=0; i<rhs.maxElements; i++)
{
this->pointer[i] = rhs.pointer[i];
}
}
return *this;
}
template <typename T>
CGenericList<T>::CGenericList(int size)
:N(0)
,maxElements(size)
{
this->pointer = new T[size];
}
template <typename T>
CGenericList<T>::~CGenericList()
{
delete[] this->pointer;
}
int main(int /*argc*/, char */*argv*/[])
{
CGenericList<CGenericList<int> > list;
list.resize();
return 0;
}
If you don't like to use stl you can have a look at stlport
Your resize is not exception safe. You are first deleting the existing array and then allocating memory for a different size and then assigning auxPointer.
Coming to the problem you are having, check if the below approach helps.
T* auxPointer = new T[this->maxElements*2];
for ( int i =0; i < this->maxElements; ++i)
std::swap(auxPointer[i], pointer[i]);
delete[] this->pointer;
this->pointer = auxPointer;
this->maxElements=2*this->maxElements;