Declaring struct members that are initialised later (C++) - c++

I need to have a variable that is declared in a struct to be initialised with a value later. It's basically because its initialisation depends on another member of the structure, which only has a value after some functions have been done.
This sounds a bit weird, so I'll show my code:
struct frame
{
Mat thresholded;
vector<vector<Point> > contrs;
vector<Moments> momts;
};
frame obj_detect(frame img)
{
// Get contours from image
findContours(img.thresholded, img.contrs, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
// Initialise moments vector big enough for all contours' moments
img.moments(img.contrs.size());
...
return img;
}
int main()
{
frame frame1;
frame1 = obj_detect(frame1);
...
}
Currently this code throws this error:
error: no match for call to ‘(std::vector<cv::Moments>) (std::vector<std::vector<cv::Point_<int> > >::size_type)’
How should I initialise the moments vector array so that it has enough space for all the contours?

There's nothing wrong or weird about what you're trying to do. This is an example of an initializer function (or what would be called a constructor for a class).
What isn't entirely clear is whether struct1 is meant to be the struct you are initializing or if it is an input that you are using to return a new struct (since your function does define its return type as my_struct as well). In either case, it is generally recommended to pass your structs by reference rather than by value or as return values.
You could try something like this:
void my_function(const my_struct& input_struct, my_struct& output_struct)
{
...
output_struct.size = ...;
output_struct.my_array = new char[output_struct.size];
...
}
Of course, if you really are using C++, you should question why you are using a struct to represent what seems to be a string?
Once you've allocated memory this way, it is important that you free the memory as well in order to avoid memory leaks. A single object can be deallocated using delete, but an array should be deallocated using delete [], for example:
delete [] some_struct.my_array;
Additionally, it is considered good practice to set pointers to null after deallocating them to avoid referencing stale memory segments. This can be done like this:
some_struct.my_array = nullptr;
Finally, this all gets a bit tedious to manage, particularly if the lifetime and ownership of the object is more complex. To deal with this, the standard library has unique_ptr and shared_ptr objects that will automatically deallocate an object when it is no longer being used.
I don't think it makes sense to go into detail about the differences and uses of each since there are innumerable resources here and elsewhere on the topic.

Seems to me this is very simple question
my_struct my_function(my_struct struct1)
{
...
struct1.my_array = malloc(struct1.size); // Initialise the array
...
}

You have to use malloc()
char* struct1.my_array = new char[struct1.size];
Edited:
Actually you can use malloc or new. In this case - doesn't matter. If you prefer malloc you have to free memory with free(), otherwise you have to use new/delete. Usually new/delete is good to be used while creating objects, when you are dealing with structs and primitive type stick to malloc.
New/Delete operator are usually invokes constructors/destructors and they are a little bit slower than malloc/free. So why you have to pay (even a little) performance cost for nothing?

Related

Returning a vector in C++

I just read this post on SO, that discusses where in memory, STL vectors are stored. According to the accepted answer,
vector<int> temp;
the header info of the vector on the stack but the contents on the heap.
In that case, would the following code be erroneous?
vector<int> some_function() {
vector<int> some_vector;
some_vector.push_back(10);
some_vector.push_back(20);
return some_vector;
}
Should I have used vector<int> *some_vector = new vector<int> instead? Would the above code result in some code of memory allocation issues? Would this change if I used an instance of a custom class instead of int?
Your code is precisely fine.
Vectors manage all the memory they allocate for you.
It doesn't matter whether they store all their internal data using dynamic allocations, or hold some metadata as direct members (with automatic storage duration). Any dynamic allocations performed internally will be safely cleaned-up in the vector's destructor, copy constructor, and other similar special functions.
You do not need to do anything as all of that is abstracted away from your code. Your code has no visibility into that mechanism, and dynamically allocating the vector itself will not have any effect on it.
That is the purpose of them!
If you decide for dynamic allocation of the vector, you will have really hard time destroying it correctly even in very simple cases (do not forget about exceptions!). Do avoid dynamic allocation at all costs whenever possible.
In other words, your code is perfectly correct. I would not worry about copying the returned vector in memory. In these simple cases compilers (in release builds) should use return value optimization / RVO (http://en.wikipedia.org/wiki/Return_value_optimization) and create some_vector at memory of the returned object. In C++11 you can use move semantics.
But if you really do not trust the compiler using RVO, you can always pass a reference to a vector and fill it in inside the function.
//function definition
void some_function(vector<int> &v) { v.push_back(10); v.push_back(20); }
//function usage
vector<int> vec;
some_function(vec);
And back to dynamic allocation, if you really need to use it, try the pattern called RAII. Or use smart pointers.
It is not important where internally vectors define their data because you return the vector by copy.:) (by value) It is the same as if you would return an integer
int some_function()
{
int x = 10;
return x;
}

C++ New vs Malloc for dynamic memory array of Objects

I have a class Bullet that takes several arguments for its construction. However, I am using a dynamic memory array to store them. I am using C++ so i want to conform to it's standard by using the new operator to allocate the memory. The problem is that the new operator is asking for the constructor arguments when I'm allocating the array, which I don't have at that time. I can accomplish this using malloc to get the right size then fill in form there, but that's not what i want to use :) any ideas?
pBulletArray = (Bullet*) malloc(iBulletArraySize * sizeof(Bullet)); // Works
pBulletArray = new Bullet[iBulletArraySize]; // Requires constructor arguments
Thanks.
You can't.
And if you truly want to conform to C++ standards, you should use std::vector.
FYI, it would probably be even more expensive than what you're trying to achieve. If you could do this, new would call a constructor. But since you'll modify the object later on anyway, the initial construction is useless.
1) std::vector
A std::vector really is the proper C++ way to do this.
std::vector<Bullet> bullets;
bullets.reserve(10); // allocate memory for bullets without constructing any
bullets.push_back(Bullet(10.2,"Bang")); // put a Bullet in the vector.
bullets.emplace_back(10.2,"Bang"); // (C++11 only) construct a Bullet in the vector without copying.
2) new [] operator
It is also possible to do this with new, but you really shouldn't. Manually managing resources with new/delete is an advanced task, similar to template meta-programming in that it's best left to library builders, who'll use these features to build efficient, high level libraries for you. In fact to do this correctly you'll basically be implementing the internals of std::vector.
When you use the new operator to allocate an array, every element in the array is default initialized. Your code could work if you added a default constructor to Bullet:
class Bullet {
public:
Bullet() {} // default constructor
Bullet(double,std::string const &) {}
};
std::unique_ptr<Bullet[]> b = new Bullet[10]; // default construct 10 bullets
Then, when you have the real data for a Bullet you can assign it to one of the elements of the array:
b[3] = Bullet(20.3,"Bang");
Note the use of unique_ptr to ensure that proper clean-up occurs, and that it's exception safe. Doing these things manually is difficult and error prone.
3) operator new
The new operator initializes its objects in addition to allocating space for them. If you want to simply allocate space, you can use operator new.
std::unique_ptr<Bullet,void(*)(Bullet*)> bullets(
static_cast<Bullet*>(::operator new(10 * sizeof(Bullet))),
[](Bullet *b){::operator delete(b);});
(Note that the unique_ptr ensures that the storage will be deallocated but no more. Specifically, if we construct any objects in this storage we have to manually destruct them and do so in an exception safe way.)
bullets now points to storage sufficient for an array of Bullets. You can construct an array in this storage:
new (bullets.get()) Bullet[10];
However the array construction again uses default initialization for each element, which we're trying to avoid.
AFAIK C++ doesn't specify any well defined method of constructing an array without constructing the elements. I imagine this is largely because doing so would be a no-op for most (all?) C++ implementations. So while the following is technically undefined, in practice it's pretty well defined.
bool constructed[10] = {}; // a place to mark which elements are constructed
// construct some elements of the array
for(int i=0;i<10;i+=2) {
try {
// pretend bullets points to the first element of a valid array. Otherwise 'bullets.get()+i' is undefined
new (bullets.get()+i) Bullet(10.2,"Bang");
constructed = true;
} catch(...) {}
}
That will construct elements of the array without using the default constructor. You don't have to construct every element, just the ones you want to use. However when destroying the elements you have to remember to destroy only the elements that were constructed.
// destruct the elements of the array that we constructed before
for(int i=0;i<10;++i) {
if(constructed[i]) {
bullets[i].~Bullet();
}
}
// unique_ptr destructor will take care of deallocating the storage
The above is a pretty simple case. Making non-trivial uses of this method exception safe without wrapping it all up in a class is more difficult. Wrapping it up in a class basically amounts to implementing std::vector.
4) std::vector
So just use std::vector.
It's possible to do what you want -- search for "operator new" if you really want to know how. But it's almost certainly a bad idea. Instead, use std::vector, which will take care of all the annoying details for you. You can use std::vector::reserve to allocate all the memory you'll use ahead of time.
Bullet** pBulletArray = new Bullet*[iBulletArraySize];
Then populate pBulletArray:
for(int i = 0; i < iBulletArraySize; i++)
{
pBulletArray[i] = new Bullet(arg0, arg1);
}
Just don't forget to free the memory using delete afterwards.
The way C++ new normally works is allocating the memory for the class instance and then calling the constructor for that instance. You basically have already allocated the memory for your instances.
You can call only the constructor for the first instance like this:
new((void*)pBulletArray) Bullet(int foo);
Calling the constructor of the second one would look like this (and so on)
new((void*)pBulletArray+1) Bullet(int bar);
if the Bullet constructor takes an int.
If what you're really after here is just fast allocation/deallocation, then you should look into "memory pools." I'd recommend using boost's implementation, rather than trying to roll your own. In particular, you would probably want to use an "object_pool".

What's the smart way to use C++ new operator with a function?

This is a long one. I have a function that loads some image data from disk. I've tried this with three different methods, one of which doesn't work, and I'm wondering what the smartest method is.
Method 1:
I used to have it set up so that the loaded data was an argument to the function, which seemed to require allocating the space for it outside the function then passing a pointer to the allocated space. This requires knowing the size of the image ahead of time, so a helper function had to be made to get the image width and height first. The following is an example.
Pros: More explicit in the calling code that memory is being allocated and therefore should be deleted.
Cons: Need to know image size ahead of time.
// Data allocated outside the image, allocated space passed to function. This works.
// Notice that width & height are passed to the function.
size=(*width)*(*height);
image = new unsigned char[size];
void read_pgm(unsigned char *image, char *file_name, int width, int height){
// Code to read sizeof(char)*width*height bytes of data from the file into image
}
Method 2:
I thought it would be nice to have the function allocate its own data so I don't need to pass it a size. If I tried to allocate the space for it in the function, it seemed to be lost after the function ended. In the following case, the function read_pgm runs fine, but if I then try to write that data to another file, my code crashes.
Pros: Don't need to know image size ahead of time, no need to allocate data in calling code.
Cons: Doesn't work. Also, if it did, would calling it repeatedly in a loop result in a memory leak if I wasn't clearing image outside the function?
// Data allocated inside the image for a pointer passed to the function. This doesn't work.
void read_pgm(unsigned char *image, char *file_name, int *width, int *height){
size=(*width)*(*height);
image = new unsigned char[size];
// Code to read the data from the file into image
}
Method 3:
Here, the data is again allocated in the function but is handed back as a returned item. This works, i.e. I can then write the data out to another image fine. I don't understand why this works and Method 2 does not.
Pros: Same as Method 2.
Cons: Same as Method 2 except this currently works.
// Data allocated in the function, and returned. This works.
unsigned char* read_pgm(char *file_name, int *width, int *height){
// Allocate data for the image
size=(*width)*(*height);
image = new unsigned char[size];
// Code to read the data from the file into image
return image; // Return pointer to the data
}
So, my questions are:
In a case like this, is it smarter to set the function up to allocate space itself so the calling code doesn't need to supply the image size? Or is it smarter to allocate outside the function as a reminder that delete needs to be called on image at some point. Or am I wrong in thinking that this needs to be done? It seems like calling Method 2 or Method 3 in a loop would make a memory leak.
Why doesn't Method 2 work?
Thanks.
If you want to know the smart way, then the answer has to be, "None of the above". The smart way? Use a vector. That's what it's for. Because using new directly sucks. Managing the bounds of your own memory sucks. We have classes for that. And char* for string? At least make it a const char*. const std::string& better. I also have to ask- what image format are you trying to read which doesn't store the width and height of the image in the file format? Seems to me like you'd be better off reading that from the file.
std::vector<unsigned int> void ReadImage(const std::string& filename, int width, int height) {
std::vector<unsigned int> imageData(width * height);
// Read here from filestream
}
std::vector<unsigned int> imageData = ReadImage("ohai.png", 1000, 600);
You need to learn about - const correctness, RAII, and the Standard library.
Answer to question 2
In order to make it work you must pass a reference to the pointer
unsigned char * & image
Otherwise you allocate memory and the COPY of the passed pointer points to it. The original pointer object doesn't change.
Answer to question 1
Ever heard of smart pointers?
Smart pointers can be used to manipulate memory all by themselves. If you don't want to use smart pointers for some inexplicable reason, such as pseudooptimization, then I think you described the pros and cons of all methods yourself - there's always tradeoff. Up to you to decide
Method 2 doesn't work because you are passing the pointer by value, and overwriting that value locally, so the value of the pointer outside the function isn't changed. You can fix this by either passing it by reference or by passing a pointer to the pointer.
As for the other question: it's really just a matter of clearly documenting who has got the responsibility to delete the allocated data. (By the way: yes, you should deallocate otherwise you will leak). In many APIs you will see in the documentation: "the caller has the responsiblity to delete this" or "call this other function to delete the allocated data".
A good way to decouple this kind of ownership concerns is to use smart pointers (as Armen suggests).
Everything you do currently results in a memory leak, since you never delete[] anything.
First off, yes, make the dimensions variable. Second, either return a pointer to the newly allocated heap storage and remember to delete it in the caller, or return a smart container object.
A std::vector<unsigned char> would do nicely:
std::vector<unsigned char> get_image(const std::string & filename, size_t & width, size_t & height)
{
// determine width and height
/* ... */
std::vector<unsigned char> result(width * height, 0);
// read into &result[0], vector guarantees contiguous storage
return result;
}
Consider encapsulating all the functionality related to reading and "handling" the data in a class.
It should take the file path as a std::string in the constructor.
Creating the file handle, allocating the memory and reading can then be done in a separate function (something like Init). This gives you the ability to create the object when you know the file path but do the time-consuming part (the reading part) later, when you actually need it.
You can expose whatever information is necessary to the outside users (like the height or width).
The class destructor will be responsible for closing the file handle (which can be done earlier, if needed) and de-allocating the data.
You can use new and delete with your class or, better yet, use a smart pointer with your class and not just with the image data part. You can also use it "on the stack" and have its destructor called automatically when out of scope.
"2.Why doesn't Method 2 work?"
Because you're passing a pointer by copy, not by reference. You pass in a pointer, and then prompty reinitialize where that pointer points to with your new call. When the scope of the function is reached, so is the life of the local variable image, as well where all that lovely new storage went.
What you really want to do (in this case), is pass either a reference to the pointer or a pointer to the pointer so that you can change the value of the passed argument (this case a pointer), and have that change be visible outside the scope of the function.
void read_pgm(unsigned char **image, char *file_name, int *width, int *height)
{
size=(*width)*(*height);
(*image) = new unsigned char[size];
// Code to read the data from the file into image
}
There's actually a really excellent section in the C++ FAQBook on these questions.
The big issue is, as you say, ensuring that the memory is allocated in a way that ensures it doesn't leak. C++ has lots of convenient facilities to do that, the most obvious being new and delete.
The easiest thing is to allocate the storate with new in a context where it will go out of scope. So...
{
MyData *md = new MyData(args);
doSomething(md);
}
now, when md goes out of scope, it will automagically have the dtor called. Now, this trick will work pretty much everywhere.
With your method 2, you're right that written as it is, it leaks memory; the next time you do a new the reference to that last time is lost, but it's not finalized or destroyed.
A solution is to explicitly call the dtor, ie, delete it, somewhere else.
I suspect the reason it doesn't work is that image is a pointer, which is what new wants to return. but since C++ does pointers call-by-value, you're putting that address into local memory on the stack, and it disappears.
You either want a **, or even better a reference.
A third solution is that C++ does have pointer types to help with free store management. The FAQbook describes how to implement reference-counting pointers here.

C++ best practice: Returning reference vs. object

I'm trying to learn C++, and trying to understand returning objects. I seem to see 2 ways of doing this, and need to understand what is the best practice.
Option 1:
QList<Weight *> ret;
Weight *weight = new Weight(cname, "Weight");
ret.append(weight);
ret.append(c);
return &ret;
Option 2:
QList<Weight *> *ret = new QList();
Weight *weight = new Weight(cname, "Weight");
ret->append(weight);
ret->append(c);
return ret;
(of course, I may not understand this yet either).
Which way is considered best-practice, and should be followed?
Option 1 is defective. When you declare an object
QList<Weight *> ret;
it only lives in the local scope. It is destroyed when the function exits. However, you can make this work with
return ret; // no "&"
Now, although ret is destroyed, a copy is made first and passed back to the caller.
This is the generally preferred methodology. In fact, the copy-and-destroy operation (which accomplishes nothing, really) is usually elided, or optimized out and you get a fast, elegant program.
Option 2 works, but then you have a pointer to the heap. One way of looking at C++ is that the purpose of the language is to avoid manual memory management such as that. Sometimes you do want to manage objects on the heap, but option 1 still allows that:
QList<Weight *> *myList = new QList<Weight *>( getWeights() );
where getWeights is your example function. (In this case, you may have to define a copy constructor QList::QList( QList const & ), but like the previous example, it will probably not get called.)
Likewise, you probably should avoid having a list of pointers. The list should store the objects directly. Try using std::list… practice with the language features is more important than practice implementing data structures.
Use the option #1 with a slight change; instead of returning a reference to the locally created object, return its copy.
i.e. return ret;
Most C++ compilers perform Return value optimization (RVO) to optimize away the temporary object created to hold a function's return value.
In general, you should never return a reference or a pointer. Instead, return a copy of the object or return a smart pointer class which owns the object. In general, use static storage allocation unless the size varies at runtime or the lifetime of the object requires that it be allocated using dynamic storage allocation.
As has been pointed out, your example of returning by reference returns a reference to an object that no longer exists (since it has gone out of scope) and hence are invoking undefined behavior. This is the reason you should never return a reference. You should never return a raw pointer, because ownership is unclear.
It should also be noted that returning by value is incredibly cheap due to return-value optimization (RVO), and will soon be even cheaper due to the introduction of rvalue references.
passing & returning references invites responsibilty.! u need to take care that when you modify some values there are no side effects. same in the case of pointers. I reccomend you to retun objects. (BUT IT VERY-MUCH DEPENDS ON WHAT EXACTLY YOU WANT TO DO)
In ur Option 1, you return the address and Thats VERY bad as this could lead to undefined behaviour. (ret will be deallocated, but y'll access ret's address in the called function)
so use return ret;
It's generally bad practice to allocate memory that has to be freed elsewhere. That's one of the reasons we have C++ rather than just C. (But savvy programmers were writing object-oriented code in C long before the Age of Stroustrup.) Well-constructed objects have quick copy and assignment operators (sometimes using reference-counting), and they automatically free up the memory that they "own" when they are freed and their DTOR automatically is called. So you can toss them around cheerfully, rather than using pointers to them.
Therefore, depending on what you want to do, the best practice is very likely "none of the above." Whenever you are tempted to use "new" anywhere other than in a CTOR, think about it. Probably you don't want to use "new" at all. If you do, the resulting pointer should probably be wrapped in some kind of smart pointer. You can go for weeks and months without ever calling "new", because the "new" and "delete" are taken care of in standard classes or class templates like std::list and std::vector.
One exception is when you are using an old fashion library like OpenCV that sometimes requires that you create a new object, and hand off a pointer to it to the system, which takes ownership.
If QList and Weight are properly written to clean up after themselves in their DTORS, what you want is,
QList<Weight> ret();
Weight weight(cname, "Weight");
ret.append(weight);
ret.append(c);
return ret;
As already mentioned, it's better to avoid allocating memory which must be deallocated elsewhere. This is what I prefer doing (...these days):
void someFunc(QList<Weight *>& list){
// ... other code
Weight *weight = new Weight(cname, "Weight");
list.append(weight);
list.append(c);
}
// ... later ...
QList<Weight *> list;
someFunc(list)
Even better -- avoid new completely and using std::vector:
void someFunc(std::vector<Weight>& list){
// ... other code
Weight weight(cname, "Weight");
list.push_back(weight);
list.push_back(c);
}
// ... later ...
std::vector<Weight> list;
someFunc(list);
You can always use a bool or enum if you want to return a status flag.
Based on experience, do not use plain pointers because you can easily forget to add proper destruction mechanisms.
If you want to avoid copying, you can go for implementing the Weight class with copy constructor and copy operator disabled:
class Weight {
protected:
std::string name;
std::string desc;
public:
Weight (std::string n, std::string d)
: name(n), desc(d) {
std::cout << "W c-tor\n";
}
~Weight (void) {
std::cout << "W d-tor\n";
}
// disable them to prevent copying
// and generate error when compiling
Weight(const Weight&);
void operator=(const Weight&);
};
Then, for the class implementing the container, use shared_ptr or unique_ptr to implement the data member:
template <typename T>
class QList {
protected:
std::vector<std::shared_ptr<T>> v;
public:
QList (void) {
std::cout << "Q c-tor\n";
}
~QList (void) {
std::cout << "Q d-tor\n";
}
// disable them to prevent copying
QList(const QList&);
void operator=(const QList&);
void append(T& t) {
v.push_back(std::shared_ptr<T>(&t));
}
};
Your function for adding an element would make use or Return Value Optimization and would not call the copy constructor (which is not defined):
QList<Weight> create (void) {
QList<Weight> ret;
Weight& weight = *(new Weight("cname", "Weight"));
ret.append(weight);
return ret;
}
On adding an element, the let the container take the ownership of the object, so do not deallocate it:
QList<Weight> ql = create();
ql.append(*(new Weight("aname", "Height")));
// this generates segmentation fault because
// the object would be deallocated twice
Weight w("aname", "Height");
ql.append(w);
Or, better, force the user to pass your QList implementation only smart pointers:
void append(std::shared_ptr<T> t) {
v.push_back(t);
}
And outside class QList you'll use it like:
Weight * pw = new Weight("aname", "Height");
ql.append(std::shared_ptr<Weight>(pw));
Using shared_ptr you could also 'take' objects from collection, make copies, remove from collection but use locally - behind the scenes it would be only the same only object.
All of these are valid answers, avoid Pointers, use copy constructors, etc. Unless you need to create a program that needs good performance, in my experience most of the performance related problems are with the copy constructors, and the overhead caused by them. (And smart pointers are not any better on this field, I'd to remove all my boost code and do the manual delete because it was taking too much milliseconds to do its job).
If you're creating a "simple" program (although "simple" means you should go with java or C#) then use copy constructors, avoid pointers and use smart pointers to deallocate the used memory, if you're creating a complex programs or you need a good performance, use pointers all over the place, and avoid copy constructors (if possible), just create your set of rules to delete pointers and use valgrind to detect memory leaks,
Maybe I will get some negative points, but I think you'll need to get the full picture to take your design choices.
I think that saying "if you're returning pointers your design is wrong" is little misleading. The output parameters tends to be confusing because it's not a natural choice for "returning" results.
I know this question is old, but I don't see any other argument pointing out the performance overhead of that design choices.

Prototype for function that allocates memory on the heap (C/C++)

I'm fairly new to C++ so this is probably somewhat of a beginner question. It regards the "proper" style for doing something I suspect to be rather common.
I'm writing a function that, in performing its duties, allocates memory on the heap for use by the caller. I'm curious about what a good prototype for this function should look like. Right now I've got:
int f(char** buffer);
To use it, I would write:
char* data;
int data_length = f(&data);
// ...
delete[] data;
However, the fact that I'm passing a pointer to a pointer tips me off that I'm probably doing this the wrong way.
Anyone care to enlighten me?
In C, that would have been more or less legal.
In C++, functions typically shouldn't do that. You should try to use RAII to guarantee memory doesn't get leaked.
And now you might say "how would it leak memory, I call delete[] just there!", but what if an exception is thrown at the // ... lines?
Depending on what exactly the functions are meant to do, you have several options to consider. One obvious one is to replace the array with a vector:
std::vector<char> f();
std::vector<char> data = f();
int data_length = data.size();
// ...
//delete[] data;
and now we no longer need to explicitly delete, because the vector is allocated on the stack, and its destructor is called when it goes out of scope.
I should mention, in response to comments, that the above implies a copy of the vector, which could potentially be expensive. Most compilers will, if the f function is not too complex, optimize that copy away so this will be fine. (and if the function isn't called too often, the overhead won't matter anyway). But if that doesn't happen, you could instead pass an empty array to the f function by reference, and have f store its data in that instead of returning a new vector.
If the performance of returning a copy is unacceptable, another alternative would be to decouple the choice of container entirely, and use iterators instead:
// definition of f
template <typename iter>
void f(iter out);
// use of f
std::vector<char> vec;
f(std::back_inserter(vec));
Now the usual iterator operations can be used (*out to reference or write to the current element, and ++out to move the iterator forward to the next element) -- and more importantly, all the standard algorithms will now work. You could use std::copy to copy the data to the iterator, for example. This is the approach usually chosen by the standard library (ie. it is a good idea;)) when a function has to return a sequence of data.
Another option would be to make your own object taking responsibility for the allocation/deallocation:
struct f { // simplified for the sake of example. In the real world, it should be given a proper copy constructor + assignment operator, or they should be made inaccessible to avoid copying the object
f(){
// do whatever the f function was originally meant to do here
size = ???
data = new char[size];
}
~f() { delete[] data; }
int size;
char* data;
};
f data;
int data_length = data.size;
// ...
//delete[] data;
And again we no longer need to explicitly delete because the allocation is managed by an object on the stack. The latter is obviously more work, and there's more room for errors, so if the standard vector class (or other standard library components) do the job, prefer them. This example is only if you need something customized to your situation.
The general rule of thumb in C++ is that "if you're writing a delete or delete[] outside a RAII object, you're doing it wrong. If you're writing a new or `new[] outside a RAII object, you're doing it wrong, unless the result is immediately passed to a smart pointer"
In 'proper' C++ you would return an object that contains the memory allocation somewhere inside of it. Something like a std::vector.
Your function should not return a naked pointer to some memory. The pointer, after all, can be copied. Then you have the ownership problem: Who actually owns the memory and should delete it? You also have the problem that a naked pointer might point to a single object on the stack, on the heap, or to a static object. It could also point to an array at these places. Given that all you return is a pointer, how are users supposed to know?
What you should do instead is to return an object that manages its resource in an appropriate way. (Look up RAII.) Give the fact that the resource in this case is an array of char, either a std::string or a std::vector seem to be best:
int f(std::vector<char>& buffer);
std::vector<char> buffer;
int result = f(buffer);
Why not do the same way as malloc() - void* malloc( size_t numberOfBytes )? This way the number of bytes is the input parameter and the allocated block address is the return value.
UPD:
In comments you say that f() basically performs some action besides allocating memory. In this case using std::vector is a much better way.
void f( std::vector<char>& buffer )
{
buffer.clear();
// generate data and add it to the vector
}
the caller will just pass an allocated vector:
std::vector buffer;
f( buffer );
//f.size() now will return the number of elements to work with
Pass the pointer by reference...
int f(char* &buffer)
However you may wish to consider using reference counted pointers such as boost::shared_array to manage the memory if you are just starting this out.
e.g.
int f(boost::shared_array<char> &buffer)
Use RAII (Resource Acquisition Is Initialization) design pattern.
http://en.wikipedia.org/wiki/RAII
Understanding the meaning of the term and the concept - RAII (Resource Acquisition is Initialization)
Just return the pointer:
char * f() {
return new char[100];
}
Having said that, you probably do not need to mess with explicit allocation like this - instead of arrays of char, use std::string or std::vector<char> instead.
If all f() does with the buffer is to return it (and its length), let it just return the length, and have the caller new it. If f() also does something with the buffer, then do as polyglot suggeted.
Of course, there may be a better design for the problem you want to solve, but for us to suggest anything would require that you provide more context.
The proper style is probably not to use a char* but a std::vector or a std::string depending on what you are using char* for.
About the problem of passing a parameter to be modified, instead of passing a pointer, pass a reference. In your case:
int f(char*&);
and if you follow the first advice:
int f(std::string&);
or
int f(std::vector<char>&);
Actually, the smart thing to do would be to put that pointer in a class. That way you have better control over its destruction, and the interface is much less confusing to the user.
class Cookie {
public:
Cookie () : pointer (new char[100]) {};
~Cookie () {
delete[] pointer;
}
private:
char * pointer;
// Prevent copying. Otherwise we have to make these "smart" to prevent
// destruction issues.
Cookie(const Cookie&);
Cookie& operator=(const Cookie&);
};
Provided that f does a new[] to match, it will work, but it's not very idiomatic.
Assuming that f fills in the data and is not just a malloc()-alike you would be better wrapping the allocation up as a std::vector<char>
void f(std::vector<char> &buffer)
{
// compute length
int len = ...
std::vector<char> data(len);
// fill in data
...
buffer.swap(data);
}
EDIT -- remove the spurious * from the signature
I guess you are trying to allocate a one dimensional array. If so, you don't need to pass a pointer to pointer.
int f(char* &buffer)
should be sufficient. And the usage scenario would be:
char* data;
int data_length = f(data);
// ...
delete[] data;