Better variant of getting the output dynamically-allocated array from the function? - c++

Here is two variants. First:
int n = 42;
int* some_function(int* input)
{
int* result = new int[n];
// some code
return result;
}
int main()
{
int* input = new int[n];
int* output = some_function(input);
delete[] input;
delete[] output;
return 0;
}
Here the function returns the memory, allocated inside the function.
Second variant:
int n = 42;
void some_function(int* input, int* output)
{
// some code
}
int main()
{
int* input = new int[n];
int* output = new int[n];
some_function(input, output);
delete[] input;
delete[] output;
return 0;
}
Here the memory is allocated outside the function.
Now I use the first variant. But I know that many built-in c++ functions use the second variant.
The first variant is more comfortable (in my opinion). But the second one also has some advantages (you allocate and delete memory in the same block).
Maybe it's a silly question but what variant is better and why?

Third variant
const int n = 42;
template<class It1, class It2>
void some_function(It1 First, It1 Last, It2 output)
{
// some code
}
void main()
{
std::vector<int> input(n);
std::vector<int> output(n);
some_function(input.begin(), input.end(), output.begin());
}

I think second variant is better, because you have "balanced responsibility over pointer". That makes code more readable, because you see where you allocate and where you free your memory.
If you want to use first variant, I'd suggest you to make dual funnction some_function_free(). As for malloc/free, new/delete, new[]/delete[], etc. Even that it will do simple delete[], by using this you'll save time when you'll want to change the way you allocate memory.

Neither variant is preferred C++ style, especially in the presence of exceptions. If an exception is thrown somewhere (either in the allocation of output or in the body of some_function) one or both of your dynamically allocated arrays will leak memory. The preferred way is to use the Resource Allocation Is Initialization (RAII) concept. Safe C++ code uses objects to acquire resources. Their destructors free those resources. As the stack unwinds from an exception, any resources acquired to that point are safely released.
In the case of dynamically allocated arrays, that means std::vector. If it doesn't adversely affect your performance (profile it if you're worried), you can even return one by value.
// don't need the global variable anymore
std::vector<int> some_function(std::vector<int> &input)
{
std::vector<int> result;
// do something
return result;
}
int main() // main returns int, not void
{
std::vector<int> input;
// insert some values
std::vector<int> output = some_function(input);
return 0;
}
No more need to worry about who is responsible for allocating and freeing memory. Your code becomes clearer and exception-safe.

Generally speaking, it's better for functions not to heap-allocate and return objects, if practicable. It creates ownership issues, and complicates the interface (the caller has to know how to manage the lifespan of the returned object). It also puts more pressure on the memory allocator, which can in turn create thread contention, and denies the caller the opportunity to avoid this cost by allocating space for things more judiciously.

There's another benefit to the second one in that it does not require heap allocation. You can call the code using stack allocated memory only:
int main()
{
int input[10];
int output[10];
some_function(input, output);
}

Related

How could I create my own string-type vector with new string instead of allocator?

I wrote a very simple code just to see if the allocator would work as allocating memory for string. And it works. However, I would like to know if I could achieve the same effect with new keyword. If I could, which method would be a better practice ? My code sample is as following:
#include<iostream>
#include<string>
#include<memory>
class MyVector{
private:
int size;
int capacity;
std::allocator<std::string> str;
std::string*a;
void allocate(){
capacity = (size-1)*2;
std::string*temp = str.allocate(capacity);
for(int i=0; i<this->getSize();++i){
temp[i] = a[i];
}
str.deallocate(a, 1);
a = temp;
}
public:
MyVector():size(0), capacity(1), a(str.allocate(1)){};
int getSize(){return size;};
int getCapacity(){return capacity;};
void pushBack(std::string input){
++size;
if(this->getSize()>this->getCapacity()){
this->allocate();
}
a[this->getSize()-1]=input;
}
std::string at(int index){
for(int i=0; i<this->getSize();++i){
if(i==index){
return a[i];
}
}
return 0;
}
};
int main(){
MyVector v;
v.pushBack("Sam");
std::cout<<v.at(0)<<std::endl;
return 0;
}
If I understand your question correctly, you're trying to allocate a bunch of strings dynamically, and would like to know whether you can use operator new() to perform the allocation, and in case you can, which method is the best.
There are a few problems with your implementation I have to point out before being able to answer your question. So let's walk through it!
std::string* a doesn't get deallocated when MyVector is destroyed
This is the most obvious one. There is no destructor, and you are manually managing a raw pointer, which therefore must be deallocated! Right now, when MyVector goes out of scope, the memory pointed to by a is going to become unreachable, and there will be no garbage collector to clean it up.
Therefore we'd have to add a method like this:
~MyVector() { str.deallocate(a, capacity); }
What if this->allocate() can't allocate, and throws std::bad_alloc when you're doing a push_back?
size has already been incremented, and the capacity has been updated but the string you were trying to push hasn't been copied, and the buffer hasn't grown, which leaves your container in an invalid state. You would probably end up accessing memory outside of the bounds of your buffer, which is undefined behavior (this could work, crash, or even get your male cat pregnant)
Alright, this can be fixed easily by putting the assignments after the actual allocation has happened. No big deal. Right?
What if when trying to copy the strings from the old buffer to the new, one of them can't allocate its own internal buffer?
Well it's going to throw std::bad_alloc in the middle of the loop. And your temp buffer is never going to be deallocated. Ouch.
This is getting serious. We could put a catch clause in there, but this is starting to be a lot of code just for maintaining the pointer in a good state.
Isn't temp[i] = a[i]; calling the assignment operator on uninitialized memory, which would be another undefined behavior?
I'm not 100% certain on this one, but my C++ instinct tells me this is pretty risky.
So, how do I get out of this long list of issues?
Use new instead? Maybe new[] because this is an array of strings?
Well, this would be cleaner, especially if you're going to use the default std::allocator anyway.
But wait, there's better!
Looking at the C++ Core Guidelines, we can see under P.8 that we shouldn't leak any resources, it is advised to use RAII, and to look for "naked new". Basically, what that means is that you should avoid using new in normal code to allocate resources dynamically. Instead, the guidelines encourage you to use unique_ptr and to use make_unique() to construct objects owned by unique_ptrs
As a reference, here is unique_ptr's page on cppreference. You can also read a bit more about it here, or watch one of the designers of the language explain the concepts I touched on much better than I could on YouTube
Following these guidelines, your code could become much more modern-conforming. It would look like this:
#include<string>
#include<memory>
class MyVector{
private:
int size;
int capacity;
std::unique_ptr<std::string[]> a;
void allocate(){
size_t new_capacity = size*2;
auto temp = std::make_unique<std::string[]>(new_capacity);
std::copy(a.get(), a.get()+size, temp.get());
capacity = new_capacity; // We have finished all the operations that could throw!
std::swap(a, temp); // Because this can't throw
}
public:
MyVector():size(0), capacity(1) {}
// Since unique_ptr<>'s destructor is called automatically
// we don't need to do it explicitely!
int getSize(){return size;};
int getCapacity(){return capacity;};
void pushBack(std::string input){
if(this->getSize() == this->getCapacity()){ // We have to change the comparison
this->allocate();
}
a[this->getSize()] = input; // This could throw too!
++size;
}
std::string at(int index){
if(index >= size)
throw std::out_of_range("Trying to access an element past the end in MyVector!");
return a.get()[index];
}
};
One final note
This container is still pretty inefficient (a growth factor of 2 is not the theoretical best, although I don't know that much more about it), it has no notion of move semantics, it can't be copied, it can't be specialized for other types (although that wouldn't be too difficult), it doesn't have handy iterators to use with algorithms or a range-based-for loop, and so on.
It is, however a very good learning exercise, and I applaud you for trying to improve on it by posting your result on StackOverflow :)
Making a production-ready container is actually a lot of work, and requires quite deep hardware knowledge to get right, so as a conclusion I would advise you to stick to std::vector for when you actually need to use a vector somewhere ;)

Delete a vector without deleting the array

I'm trying to populate a vector of doubles in C++ and pass the associated array to Fortran. But I'm having trouble freeing the rest of the memory associated with the vector. I'd like to avoid copying. Here's what I have:
std::vector<double> *vec = new std::vector<double>();
(*vec).push_back(1.0);
(*vec).push_back(2.0);
*arr = (*vec).data(); //arr goes to Fortran
How do I delete vec while keeping arr intact? Is there a way to nullify the pointer to arr in vec so that I can then delete vec?
Update
I see that I didn't give enough information here. A couple things:
I'm actually calling a C++ function in Fortran using iso_c_binding
I don't know how large the vec needs to be. The vector class looks good for this situation
I might try Guillaume's suggestion eventually, but for now, I'm passing vec to the Fortran and calling another C++ function to delete it once I'm done with the data
You need to rethink your program design.
Somehow, somewhere, you need to keep an array alive while Fortran is using it. So whatever context you're using to access Fortran should probably be responsible for ownership of this array.
class fortran_context {
/*Blah blah blah whatever API you're using to access Fortran*/
void * arr;
std::vector<double> vec; //Don't allocate this as a pointer; makes no sense!
public:
fortran_context() {
arr = //Do whatever is necessary to setup Fortran stuff. I'm assuming your
//api has some kind of "get_array_pointer" function that you'll use.
}
~fortran_context() {
//Do the cleanup for the fortran stuff
}
//If you want to spend time figuring out a robust copy constructor, you may.
//Personally, I suspect it's better to just delete it, and make this object non-copyable.
fortran_context(fortran_context const&) = delete;
std::vector<double> & get_vector() {
return vec;
}
std::vector<double> const& get_vector() const {
return vec;
}
void assign_vector_to_array() {
*arr = vec.data();
}
void do_stuff_with_fortran() {
assign_vector_to_array();
//???
}
};
int main() {
fortran_context context;
auto & vec = context.get_vector();
vec.push_back(1.0);
vec.push_back(2.0);
context.do_stuff_with_fortran();
return 0;
} //Cleanup happens automatically due to correct implementation of ~fortran_context()
I've abstracted a lot of this because I don't know what API you're using to access Fortran, and I don't know what kind of work you're doing with this array. But this is, by far, the safest way to ensure that
The vector's allocated memory exists so long as you are doing stuff in Fortran
The memory associated with the vector will be cleaned up properly when you're done.
How do I delete vec while keeping arr intact? Is there a way to nullify the pointer to arr in vec so that I can then delete vec?
The library does not provide any built-in capability to do that. You have to do the bookkeeping work yourself.
Allocate memory for the data and copy data from the vector.
Send the data to FORTRAN.
Decide when it is safe to deallocate the data and then delete them.
// Fill up data in vec
std::vector<double> vec;
vec.push_back(1.0);
vec.push_back(2.0);
// Allocate memory for arr and copy the data from vec
double* arr = new double[vec.size()];
std::copy(vec.begin(), vec.end(), arr);
// use arr
// delete arr
delete [] arr;
What you are asking for is not possible. std::vector, being a well behaved template class will release the internals that it owns and manages when it is destroyed.
You will have to keep vector alive while you are using its contents, which makes perfect sense. Otherwise, you will have to make a copy.
Also, I don't see why you are allocating the vector on the heap, it doesn't seem needed at all.
How do I delete vec while keeping arr intact? Is there a way to nullify the pointer to arr in vec so that I can then delete vec?
You don't.
I think you misuse or misunderstood what vector is for. It is not meant to expose memory management of the underlying array, but to represent a dynamically sized array as a regular type.
If you need to explicitly manage memory, I'd suggest you to use std::unique_ptr<T[]>. Since unique pointers offers a way to manage memory and to release it's resource without deleting it, I think it's a good candidate to meet your needs.
auto arr = std::make_unique<double[]>(2);
arr[0] = 1.;
arr[1] = 2.;
auto data = arr.release();
// You have to manage `data` memory manually,
// since the unique pointer released it's resource.
// arr is null here
// data is a pointer to an array, must be deleted manually later.
delete[] data;

How does an allocator create and destroy an array?

How does an allocator create and destroy and array, for example
int* someInt = someAllocator(3);
Where without the allocator it would just be
int* someInt = new int[3];
Where the allocator is responsible for create each element and ensuring the constructor will be called.
How is the internals for an allocator written without the use of new? Could someone provide and example of the function?
I do not want to just use std::vector as I am trying to learn how an allocator will create an array.
The problem of general memory allocation is a surprisingly tricky one. Some consider it solved and some unsolvable ;) If you are interested in internals, start by taking a look at Doug Lea's malloc.
The specialized memory allocators are typically much simpler - they trade the generality (e.g. by making the size fixed) for simplicity and performance. Be careful though, using general memory allocation is usually better than a hodge-podge of special allocators in realistic programs.
Once a block of memory is allocated through the "magic" of the memory allocator, it can be initialized at container's pleasure using placement new.
--- EDIT ---
The placement new is not useful for "normal" programming - you'd only need it when implementing your own container to separate memory allocation from object construction. That being said, here is a slightly contrived example for using placement new:
#include <new> // For placement new.
#include <cassert>
#include <iostream>
class A {
public:
A(int x) : X(x) {
std::cout << "A" << std::endl;
}
~A() {
std::cout << "~A" << std::endl;
}
int X;
};
int main() {
// Allocate a "dummy" block of memory large enough for A.
// Here, we simply use stack, but this could be returned from some allocator.
char memory_block[sizeof(A)];
// Construct A in that memory using placement new.
A* a = new(memory_block) A(33);
// Yup, it really is constructed!
assert(a->X == 33);
// Destroy the object, wihout freeing the underlying memory
// (which would be disaster in this case, since it is on stack).
a->~A();
return 0;
}
This prints:
A
~A
--- EDIT 2 ---
OK, here is how you do it for the array:
int main() {
// Number of objects in the array.
const size_t count = 3;
// Block of memory big enough to fit 'count' objects.
char memory_block[sizeof(A) * count];
// To make pointer arithmetic slightly easier.
A* arr = reinterpret_cast<A*>(memory_block);
// Construct all 3 elements, each with different parameter.
// We could have just as easily skipped some elements (e.g. if we
// allocated more memory than is needed to fit the actual objects).
for (int i = 0; i < count; ++i)
new(arr + i) A(i * 10);
// Yup, all of them are constructed!
for (int i = 0; i < count; ++i) {
assert(arr[i].X == i * 10);
}
// Destroy them all, without freeing the memory.
for (int i = 0; i < count; ++i)
arr[i].~A();
return 0;
}
BTW, if A had a default constructor, you could try call it on all elements like this...
new(arr) A[count];
...but this would open a can of worms you really wouldn't want to deal with.
I've written about it in my second example here:
How to create an array while potentially using placement new
The difference is that the t_allocator::t_array_record would be managed by the allocator rather than the client.

C++ Allocate Memory Without Activating Constructors

I'm reading in values from a file which I will store in memory as I read them in. I've read on here that the correct way to handle memory location in C++ is to always use new/delete, but if I do:
DataType* foo = new DataType[sizeof(DataType) * numDataTypes];
Then that's going to call the default constructor for each instance created, and I don't want that. I was going to do this:
DataType* foo;
char* tempBuffer=new char[sizeof(DataType) * numDataTypes];
foo=(DataType*) tempBuffer;
But I figured that would be something poo-poo'd for some kind of type-unsafeness. So what should I do?
And in researching for this question now I've seen that some people are saying arrays are bad and vectors are good. I was trying to use arrays more because I thought I was being a bad boy by filling my programs with (what I thought were) slower vectors. What should I be using???
Use vectors!!! Since you know the number of elements, make sure that you reserve the memory first (by calling myVector.reserve(numObjects) before you then insert the elements.).
By doing this, you will not call the default constructors of your class.
So use
std::vector<DataType> myVector; // does not reserve anything
...
myVector.reserve(numObjects); // tells vector to reserve memory
You can use ::operator new to allocate an arbitrarily sized hunk of memory.
DataType* foo = static_cast<DataType*>(::operator new(sizeof(DataType) * numDataTypes));
The main advantage of using ::operator new over malloc here is that it throws on failure and will integrate with any new_handlers etc. You'll need to clean up the memory with ::operator delete
::operator delete(foo);
Regular new Something will of course invoke the constructor, that's the point of new after all.
It is one thing to avoid extra constructions (e.g. default constructor) or to defer them for performance reasons, it is another to skip any constructor altogether. I get the impression you have code like
DataType dt;
read(fd, &dt, sizeof(dt));
If you're doing that, you're already throwing type safety out the window anyway.
Why are you trying to accomplish by not invoking the constructor?
You can allocate memory with new char[], call the constructor you want for each element in the array, and then everything will be type-safe. Read What are uses of the C++ construct "placement new"?
That's how std::vector works underneath, since it allocates a little extra memory for efficiency, but doesn't construct any objects in the extra memory until they're actually needed.
You should be using a vector. It will allow you to construct its contents one-by-one (via push_back or the like), which sounds like what you're wanting to do.
I think you shouldn't care about efficiency using vector if you will not insert new elements anywhere but at the end of the vector (since elements of vector are stored in a contiguous memory block).
vector<DataType> dataTypeVec(numDataTypes);
And as you've been told, your first line there contains a bug (no need to multiply by sizeof).
Building on what others have said, if you ran this program while piping in a text file of integers that would fill the data field of the below class, like:
./allocate < ints.txt
Then you can do:
#include <vector>
#include <iostream>
using namespace std;
class MyDataType {
public:
int dataField;
};
int main() {
const int TO_RESERVE = 10;
vector<MyDataType> everything;
everything.reserve( TO_RESERVE );
MyDataType temp;
while( cin >> temp.dataField ) {
everything.push_back( temp );
}
for( unsigned i = 0; i < everything.size(); i++ ) {
cout << everything[i].dataField;
if( i < everything.size() - 1 ) {
cout << ", ";
}
}
}
Which, for me with a list of 4 integers, gives:
5, 6, 2, 6

How do I return an array from a function?

I don't get a error message when I compile the code but I cant a proper result.
#include <iostream>
using namespace std;
struct Coord{
int r;
int c;
};
struct CoordwValue{
Coord C;
char Value;
};
CoordwValue* getNeighbors();
int main (){
CoordwValue *k= getNeighbors();
for (int i=0;i<4;i++)
cout<<(k[i].Value);
}
CoordwValue *getNeighbors(){
CoordwValue Neighbors[4];
Neighbors->Value='X';
Neighbors->C.r= 0;
Neighbors->C.c= 1;
(Neighbors+1)->Value='0';
(Neighbors+1)->C.r= 1;
(Neighbors+1)->C.c= 2;
(Neighbors+2)->Value='1';
(Neighbors+2)->C.r= 2;
(Neighbors+2)->C.c= 1;
(Neighbors+3)->Value='X';
(Neighbors+3)->C.r= 1;
(Neighbors+3)->C.c= 0;
//for (int i=0;i<4;i++)
// cout<<Neighbors[i].Value;
return Neighbors;
}
This part of the code prints X01X
for (int i=0;i<4;i++)
cout<<Neighbors[i].Value;
But I can't get the same result from
for (int i=0;i<4;i++)
cout<<(k[i].Value);
What is the problem?
Edit:
This version of the code works fine.
#include <iostream>
using namespace std;
char* getNeighbors();
int main (){
char *k= getNeighbors();
for (int i=0;i<4;i++)
cout<<(*(k+i));
}
char *getNeighbors(Coord C, int r){
char Neighbors[4];
*Neighbors='X';
*(Neighbors+1)='0';
*(Neighbors+2)='1';
*(Neighbors+3)='X'
return Neighbors;
}
You are returning a pointer to a stack-allocated array. This array will cease to exist when the function returns, so the pointer will effectively be invalid though it may still work (until you call another function, such as cout, when it will probably be wiped out by the new stack segment). You probably want to say this:
CoordwValue *Neighbors = new CoordwValue[4];
Instead of this:
CoordwValue Neighbors[4];
Of course, then it's up to the calling function (main in this case) to properly delete[] the array when it is finished using it.
If you want to return an array of four objects, you don't necessarily need to use dynamic allocation or std::vector. You just need to wrap the array in a class so that you can return it. For example:
struct GetNeighborsResult
{
CoordwValue Value[4];
};
GetNeighborsResult getNeighbors();
Boost, TR1, and C++0x all have a container-like array class template that you can easily use for this purpose:
std::array<CoordwValue, 4> getNeighbors();
The advantage of using array is that you don't have to write a separate class for every type and number that you have, you can just use the class template.
If you do choose to return a pointer to a dynamically allocated array, use a smart pointer to manage the memory. There is no reason whatsoever to not use a smart pointer.
Returned array is created on the stack and returned. I'd suggest to read about difference of heap and stack memory here.
If array needs to be returned from a function you have an option of allocating memory dynamically using new. However, then the memory must be released with delete or it will result in a memory leak.
STL containers use dynamic memory and have overloaded copy constructor. Replacing array with vector<T> will allow you to return the values safely.
The problem is that you are returning a variable on the stack. The variable Neighbors is created in on the stack in the method getNeighbors. When you leave this method, the memory is destroyed, corrupting your return value.
How to fix it? Pass in an array created on the outside and fill the values in.
You are returning the address of a local variable. When getNeighbors returns, Neighbors[4] goes out of scope, causing all sorts of problems, including what should be a compiler warning/error.
You have a couple of options around this: first, do what cdhowie said and return a dynamically allocated array. Another is to return by value, so the return is a COPY of Neighbors[4], not a pointer to it. I think the syntax for this would be something like CoordwValue getNeighbors()[4] { .... }
Yet another is to have the caller pass in a pre-allocated array that you fill in.