Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Coding style when using the stack for memory management in C/C++

Tags:

c++

c

stack

memory

Coming from a Java background, I'm trying to learn how to handle memory (de)allocation in C/C++ in the simplest way.

A colleague suggested that I only allocate memory for member variables and let the stack handle the local variables. I'm not entirely sure what this concept is called, but it means that functions would be implemented like this:

void inc(int x, int &y){
  y=x+1;
}

Another way would be this:

int inc(int x, int &y){
  y=x+1;
  return y;
}

First one prohibits me from using it in an expression, i.e:

int y;
inc(2,y); 
inc(y,y);

Second one does, but it isn't pretty:

int y;
y=inc(inc(2,y),y);

Before I go mess up my code, what do seasoned C/C++ programmers think about this coding style?

like image 402
Grav Avatar asked Sep 19 '26 05:09

Grav


2 Answers

I would heavily discourage

int inc(int x, int &y) {
   y=x+1;
   return y;
}

To the programmer using this function, it's not clear why the function modifies an input, and returns the value, and they're both the same object.


Really, to my mind, the choice is between:

// #1
void inc(int x, int& y) {
   y=x+1;
}

int y = 0;
inc(2, y);

and

// #2
int inc(int x) {
   return x+1;
}

int y = inc(2);

In the general case, I still prefer #2 as I find "out parameters" archaic and clunky to use. As you point out, you end up struggling with expressions and it's not terribly clear what's actually going on when you invoke the function1.

Then again, if you have an object more complex than int (say, an array, or a large class, or you just want to "return" more than one object), it may make object ownership easier to deal with if you're not creating any new objects inside the function, making #1 the more convenient choice.

I think the conclusion I'm trying to draw here, is that it depends on the scenario. Trying to generalise about these things is a fool's errand.


1 - Using pointers rather than references solves that somewhat, though it does introduce bloat with now having to bother checking for invalid pointers:

// #3
void inc(int x, int* y) {
   assert(y); // at least, we can check that it's not NULL
   *y = x+1;
}

int y = 0;
inc(2, &y); // clear here that I'm passing a pointer
like image 139
Lightness Races in Orbit Avatar answered Sep 21 '26 18:09

Lightness Races in Orbit


There is a third much simpler way:

int inc( int x ) {
   return x+1;
}

int y = inc(inc(2));
like image 28
David Rodríguez - dribeas Avatar answered Sep 21 '26 20:09

David Rodríguez - dribeas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!