Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Consequences of only using stack in C++

Lets say I know a guy who is new to C++. He does not pass around pointers (rightly so) but he refuses to pass by reference. He uses pass by value always. Reason being that he feels that "passing objects by reference is a sign of a broken design".

The program is a small graphics program and most of the passing in question is mathematical Vector(3-tuple) objects. There are some big controller objects but nothing more complicated than that.

I'm finding it hard to find a killer argument against only using the stack.

I would argue that pass by value is fine for small objects such as vectors but even then there is a lot of unnecessary copying occurring in the code. Passing large objects by value is obviously wasteful and most likely not what you want functionally.

On the pro side, I believe the stack is faster at allocating/deallocating memory and has a constant allocation time.

The only major argument I can think of is that the stack could possibly overflow, but I'm guessing that it is improbable that this will occur? Are there any other arguments against using only the stack/pass by value as opposed to pass by reference?

like image 562
BefittingTheorem Avatar asked Sep 12 '10 14:09

BefittingTheorem


People also ask

Why stack is used in C?

A stack is a linear data structure, collection of items of the same type. Stack follows the Last In First Out (LIFO) fashion wherein the last element entered is the first one to be popped out. In stacks, the insertion and deletion of elements happen only at one endpoint of it.

Can we use stack in C?

Implementing Stack in C Stacks can be represented using structures, pointers, arrays or linked lists. Here, We have implemented stacks using arrays in C.

Is there a stack library in C?

The pop and return external functions are provided with the argument stack library. The pop external functions are described below according to the data type of the value that each pops from the argument stack. The return external functions are described in Return functions for C.

What are the methods to implement stack in C?

There are two ways to implement a stack: Using array. Using linked list.


5 Answers

Subtyping-polymorphism is a case where passing by value wouldn't work because you would slice the derived class to its base class. Maybe to some, using subtyping-polymorphism is bad design?

like image 199
stefaanv Avatar answered Sep 22 '22 02:09

stefaanv


Your friend's problem is not his idea as much as his religion. Given any function, always consider the pros and cons of passing by value, reference, const reference, pointer or smart pointer. Then decide.

The only sign of broken design I see here is your friend's blind religion.

That said, there are a few signatures that don't bring much to the table. Taking a const by value might be silly, because if you promise not to change the object then you might as well not make your own copy of it. Unless its a primitive, of course, in which case the compiler can be smart enough to take a reference still. Or, sometimes it's clumsy to take a pointer to a pointer as argument. This adds complexity; instead, you might be able to get away with it by taking a reference to a pointer, and get the same effect.

But don't take these guidelines as set in stone; always consider your options because there is no formal proof that eliminates any alternative's usefulness.

  1. If you need to change the argument for your own needs, but don't want to affect the client, then take the argument by value.
  2. If you want to provide a service to the client, and the client is not closely related to the service, then consider taking an argument by reference.
  3. If the client is closely related to the service then consider taking no arguments but write a member function.
  4. If you wish to write a service function for a family of clients that are closely related to the service but very distinct from each other then consider taking a reference argument, and perhaps make the function a friend of the clients that need this friendship.
  5. If you don't need to change the client at all then consider taking a const-reference.
like image 32
wilhelmtell Avatar answered Sep 23 '22 02:09

wilhelmtell


There are all sorts of things that cannot be done without using references - starting with a copy constructor. References (or pointers) are fundamental and whether he likes it or not, he is using references. (One advantage, or maybe disadvantage, of references is that you do not have to alter the code, in general, to pass a (const) reference.) And there is no reason not to use references most of the time.

And yes, passing by value is OK for smallish objects without requirements for dynamic allocation, but it is still silly to hobble oneself by saying "no references" without concrete measurements that the so-called overhead is (a) perceptible and (b) significant. "Premature optimization is the root of all evil"1.

1 Various attributions, including C A Hoare (although apparently he disclaims it).

like image 27
Jonathan Leffler Avatar answered Sep 22 '22 02:09

Jonathan Leffler


I think there is a huge misunderstanding in the question itself.

There is not relationship between stack or heap allocated objects on the one hand and pass by value or reference or pointer on the other.

Stack vs Heap allocation

Always prefer stack when possible, the object's lifetime is then managed for you which is much easier to deal with.

It might not be possible in a couple of situations though:

  • Virtual construction (think of a Factory)
  • Shared Ownership (though you should always try to avoid it)

And I might miss some, but in this case you should use SBRM (Scope Bound Resources Management) to leverage the stack lifetime management abilities, for example by using smart pointers.

Pass by: value, reference, pointer

First of all, there is a difference of semantics:

  • value, const reference: the passed object will not be modified by the method
  • reference: the passed object might be modified by the method
  • pointer/const pointer: same as reference (for the behavior), but might be null

Note that some languages (the functional kind like Haskell) do not offer reference/pointer by default. The values are immutable once created. Apart from some work-arounds for dealing with the exterior environment, they are not that restricted by this use and it somehow makes debugging easier.

Your friend should learn that there is absolutely nothing wrong with pass-by-reference or pass-by-pointer: for example thing of swap, it cannot be implemented with pass-by-value.

Finally, Polymorphism does not allow pass-by-value semantics.

Now, let's speak about performances.

It's usually well accepted that built-ins should be passed by value (to avoid an indirection) and user-defined big classes should be passed by reference/pointer (to avoid copying). big in fact generally means that the Copy Constructor is not trivial.

There is however an open question regarding small user-defined classes. Some articles published recently suggest that in some case pass-by-value might allow better optimization from the compiler, for example, in this case:

Object foo(Object d) { d.bar(); return d; }

int main(int argc, char* argv[])
{
  Object o;
  o = foo(o);
  return 0;
}

Here a smart compiler is able to determine that o can be modified in place without any copying! (It is necessary that the function definition be visible I think, I don't know if Link-Time Optimization would figure it out)

Therefore, there is only one possibility to the performance issue, like always: measure.

like image 25
Matthieu M. Avatar answered Sep 21 '22 02:09

Matthieu M.


Reason being that he feels that "passing objects by reference is a sign of a broken design".

Although this is wrong in C++ for purely technical reasons, always using pass-by-value is a good enough approximation for beginners – it’s certainly much better than passing everything by pointers (or perhaps even than passing everything by reference). It will make some code inefficient but, hey! As long as this doesn’t bother your friend, don’t be unduly disturbed by this practice. Just remind him that someday he might want to reconsider.

On the other hand, this:

There are some big controller objects but nothing more complicated than that.

is a problem. Your friend is talking about broken design, and then all the code uses are a few 3D vectors and large control structures? That is a broken design. Good code achieves modularity through the use of data structures. It doesn’t seem as though this were the case.

… And once you use such data structures, code without pass-by-reference may indeed become quite inefficient.

like image 44
Konrad Rudolph Avatar answered Sep 25 '22 02:09

Konrad Rudolph