c++ stl copy function proper memory management - c++

Just on the following code do I need to allocate memory with new for floatArray or will the copy function allocate memory for me?
Also is it okay to copy a constant vector to an array this way? Why?
vector<float> floatVector;
//filled floatVector here
float *floatArray = new float[floatVector.size()];
copy(floatVector.begin(),floatVector.end(),floatArray);
delete[] floatArray;

std::copy doesn't allocate memory, you should do it yourself.

If you don't want to allocate the array first then you may use a back_inserter iterator to push elements one by one into certain containers. For some containers this is less efficient (I think) but can be very handy sometimes.
#include<iterator>
#include<vector>
#include<deque>
std::vector<float> floatVector(10,1.0);
std::deque<float> floatDeque; //memory not allocated
//insert elements of vector into deque.
std::copy(floatVector.begin(), floatVector.end(), std::back_inserter(floatDeque));

copy will not allocate for you, so yes you need to allocate it.

std::copy copies by using the arguments assignment ("=") operator or the arguments copy constructor (this is probably implementation dependent, I'm not sure right now). It does nothing but iterate through the range beginning at param.begin() to param.end() and do something like:
while (first!=last) *result++ = *first++;
Thus, you need to allocate the memory necessary yourself. Otherwise it will create undefined behaviour.
Is it OK to copy a constant vector to an array this way? Depends on what you want to do. Generally, it's fine, since the values are transferred to the target by value, not by reference, hence const-correctness is not broken.
For example, this works fine:
std::vector<int> vec;
vec.push_back(1);
vec.push_back(2);
const std::vector<int> constvec(vec);
int *arrray = new int[2];
std::copy(constvec.begin(),constvec.end(),arrray);

copy function never allocate memory but you have to allocate memory for static datastructures but for dynamic datastructures, it'll allocate memory automatically.
and this process is not good but its better to use another vector instead of that floatarray

Related

Canonical Way to Delete a Vector Allocated on The Heap in C++17

I have searched stack overflow, but it seems the previous answers are potentially outdated, or just not very clear.
My question is the following:
I want to store a huge amount of data in a vector. To do this, I will allocate the vector on the heap as follows:
#include <vector>
std::vector<int> *vector = new std::vector<int> (1000000000);
Now suppose I use this vector in a large matrix computation. I want to now free it.
What is the canonical way to do this in c++17?
I know that for an array the riff would be as follows:
int *arr = new int[1000000000];
delete[] arr
What is the equivalent (and most efficient) way to do this for an stl vector?
The thing with std::vector is that its data is always on the heap.
Hence you don't have to allocate the std::vector itself on the heap.
std::vector makes use of a principle called RAII (Resource Acquisition is Initialization), it means that when it's done with memory, it de-allocates it for you.
Hence, doing this is sufficient
{
std::vector<int> x{};
for (size_t i = 0; i < 50000; i++) x.push_back(x);
} // x gets out of scope, memory is freed
You don't have to manually free the std::vector's memory.
Now, say you'd allocate the std::vector itself on the heap, for whatever reason. Then you'd have to use delete vector; to free it. In this scenario, I would suggest std::unique_ptr<std::vector<T>> though, as it also makes use of the same principle (RAII).

Use a ::std::vector for array creation

I want to grow a ::std::vector at runtime, like that:
::std::vector<int> i;
i.push_back(100);
i.push_back(10);
At some point, the vector is finished, and i do not need the extra functionality ::std::vector provides any more, so I want to convert it to a C-Array:
int* v = i.data();
Because I will do that more than once, I want to deallocate all the heap memory ::std::vector reserved, but I want to keep the data, like that (pseudo-code):
free(/*everything from ::std::vector but the list*/);
Can anybody give me a few pointers on that?
Thanks in advance,
Jack
In all the implementations I have seen, the allocated part of a vector is... the array itself. If you know that it will no longer grow, you can try to shrink it, to release possibly unused memory:
i.shrink_to_fit();
int* v = i.data();
Of course, nothing guarantees that the implementation will do anything, but the only foolproof alternative would be to allocated a new array, move data from the vector to the array and clear the vector.
int *v = new int[i.size];
memcpy(v, i.data, i.size * sizeof(int));
i.clear();
But I really doubt that you will have a major gain that way...
You can use the contents of a std::vector as a C array without the need to copy or release anything. Just make sure that std::vector outlives the need for your pointer to be valid (and that further modifications which could trigger a reallocation are done on the vector itself).
When you obtain a pointer to internal storage through data() you're not actually allocating anything, just referring to the already allocated memory.
The only additional precaution you could use to save memory is to use shrink_to_fit() to release any excess memory used as spare capacity (though it's not guaranteed).
You have two options:
Keep data in vector, but call shrink_to_fit. All overhead you'll have - is an extra pointer (to the vector end). It is available since C++ 11
Copy data to an external array and destroy the vector object:
Here is the example:
std::vector<int> vec;
// fill vector
std::unique_ptr<int[]> arr(new int[vec.size()]);
std::copy(vec.begin(), vec.end(), arr.get());

Moving an array held by a unique_ptr into a vector's array storage

Is there a way to move a unique_ptr
unique_ptr<int[]> foo;
into a vector?
vector<int> bar;
No, you cannot just hand vector a piece of memory and expect it to use that as its array storage. A vector's storage must come from the allocator that the vector uses.
You could try to use allocator gimmicks to pawn the memory off to the vector in some way. But even that would be tricky, as the vector can allocate as many ints as it wants, regardless of what size you tell it.
You can move the contents of a unique_ptr into an element of the array. Say, if you had a vector<unique_ptr<int[]>>. But you can't just slap a piece of memory into a vector.

Can a vector allocated on the "stack" be passed from function to function?

I know that variables allocated on that stack of a function become inaccessible when the function finishes execution. However, vector types allocate their elements on the heap no matter how they are allocated. So for instance,
vector<int> A;
will allocate space for its elements on the heap instead of the stack.
My question is, assume I have the following code:
int main(int argc, char *argv[]) {
// initialize a vector
vector<int> A = initVector(100000);
// do something with the vector...
return 0;
}
// initialize the vector
vector<int> initVector(int size) {
vector<int> A (size); // initialize the vector "on the stack"
// fill the vector with a sequence of numbers...
int counter = 0;
for (vector<int>::iterator i = A.begin(); i != A.end(); i++) {
(*i) = counter++;
}
return A;
}
Will I have memory access problems when using the vector A in the main function? I tried this several times and they all worked normally, but I'm scared that this might just be luck.
The way I see it is, the vector A allocates its elements on the heap, but it has some "overhead" parameters (maybe the size of the vector) allocated on the stack itself. Therefore, using the vector in the main function might result in a memory access problem if these parameters are overwritten by another allocation. Any ideas?
When you do "return A;" you return by value, so you get a copy of the vector -- C++ creates a new instance and calls copy constructor or operator= on it. So in this case it doesn't matter where the memory was allocated as you have to copy it anyway and destroy the old copy (some possible optimizations notwithstanding).
The data in the vector (and all other STL containers) is moved around by value as well, so you store the copy of your integers, not pointers to them. That means your objects can be copied around several times in any container operation and they must implement a copy constructor and/or assignment operator correctly. C++ generates those for you by default (just calling copy ctor on all your member variables), but they don't always do the right thing.
If you want to store pointers in an STL container consider using shared pointer wrappers (std::shared_ptr or boost::shared_ptr). They will ensure the memory is handled correctly.
Yes, it will work normally because the memory for the elements are allocated and that is what will be used to build the vector<int> A = variable. However, performance wise, it is not the best idea.
I would suggest changing your function to be the following though
void initVector(vector<int>& a, int size)
For additional references on usage, please see Returning a STL vector from a function… and [C++] Returning Vector from Function.
For an additional reference on performance (using C++11), please see Proper way (move semantics) to return a std::vector from function calling in C++0x
C++ vector actually has two pieces of memory that are linked with a single pointer. The first one is in stack, and the 2nd one in heap. So you have features of both stack and heap in a single object.
std::vector<int> vec;
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
std::cout << sizeof(vec) << std::endl;
Once you run that code, you'll notice that the stack area does not contain the elements, but it still exists. So when you pass the vector from function to another, you'll need to manipulate the stack areas, and the vector will get copied like any other stack-based object.

Define array, then change its size

I come from a java background and there's something I could do in Java that I need to do in C++, but I'm not sure how to do it.
I need to declare an array, but at the moment I don't know the size. Once I know the size, then I set the size of the array. I java I would just do something like:
int [] array;
then
array = new int[someSize];
How do I do this in C++?
you want to use std::vector in most cases.
std::vector<int> array;
array.resize(someSize);
But if you insist on using new, then you have do to a bit more work than you do in Java.
int *array;
array = new int[someSize];
// then, later when you're done with array
delete [] array;
No c++ runtimes come with garbage collection by default, so the delete[] is required to avoid leaking memory. You can get the best of both worlds using a smart pointer type, but really, just use std::vector.
In C++ you can do:
int *array; // declare a pointer of type int.
array = new int[someSize]; // dynamically allocate memory using new
and once you are done using the memory..de-allocate it using delete as:
delete[]array;
Best way would be for you to use a std::vector. It does all you want and is easy to use and learn. Also, since this is C++, you should use a vector instead of an array. Here is an excellent reason as to why you should use a container class (a vector) instead of an array.
Vectors are dynamic in size and grow as you need them - just what you want.
The exact answer:
char * array = new char[64]; // 64-byte array
// New array
delete[] array;
array = new char[64];
std::vector is a much better choice in most cases, however. It does what you need without the manual delete and new commands.
As others have mentioned, std::vector is generally the way to go. The reason is that vector is very well understood, it's standardized across compilers and platforms, and above all it shields the programmer from the difficulties of manually managing memory. Moreover, vector elements are required to be allocated sequentially (i.e., vector elements A, B, C will appear in continuous memory in the same order as they were pushed into the vector). This should make the vector as cache-friendly as a regular dynamically allocated array.
While the same end result could definitely be accomplished by declaring a pointer to int and manually managing the memory, that would mean extra work:
Every time you need more memory, you must manually allocate it
You must be very careful to delete any previously allocated memory before assigning a new value to the pointer, lest you'll be stuck with huge memory leaks
Unlike std::vector, this approach is not RAII-friendly. Consider the following example:
void function()
{
int* array = new int[32];
char* somethingElse = new char[10];
// Do something useful.... No returns here, just one code path.
delete[] array;
delete[] somethingElse;
}
It looks safe and sound. But it isn't. What if, upon attempting to allocate 10 bytes for "somethingElse", the system runs out of memory? An exception of type std::bad_alloc will be thrown, which will start unwinding the stack looking for an exception handler, skipping the delete statements at the end of the function. You have a memory leak. That is but one of many reasons to avoid manually managing memory in C++. To remedy this (if you really, really want to), the Boost library provides a bunch of nice RAII wrappers, such as scoped_array and scoped_ptr.
use std::array when size is known at compile time otherwise use std::vector
#include <array>
constexpr int someSize = 10;
std::array<int, someSize> array;
or
#include <vector>
std::vector<int> array; //size = 0
array.resize(someSize); //size = someSize
Declare a pointer:
int * array;