• 0

C++ method returns (choosing a style)


Question

Alright so i can't decide on what style to choose..

//Style 1
void proc(){
     bool is_bigger;
     if(is_bigger = isBigger(2,1)){
          ...
     }
}

bool isBigger(int x, int y){
     return ( x > y )? true : false;
}
//Style 2
void proc(){
     if(isBigger(2,1)){
          ...
     }
}

bool isBigger(int x, int y){
     return ( x > y )? true : false;
}
//Style 3
void proc(){
    bool *is_bigger = new bool(false);
    if(isBigger(2,1, &is_bigger)){
     ...
    }
}

void isBigger(int x, int y, bool **ret){
    if(x >y){
         *ret = true;
    }
    *ret = false;
}
//Style 4
void proc(){
     bool *is_bigger = new bool(false);
     if(isBigger(2,1, &is_bigger)){
          ...
     }
}

bool isBigger(int x, int y, bool **ret){
    if(x >y){
         *ret = true;
         return *ret;
    }
    *ret = false;
    return *ret;
}
//Style 5
void proc(){
     bool *is_bigger = new bool(false);
     if(isBigger(2,1, &is_bigger)){
          ...
     }
}

bool* isBigger(int x, int y, bool **ret){
    if(x >y){
         *ret = true;
         return ret;
    } 
    *ret = false;
    return ret;
}

Essentially all of these fundamental routines can achieve the the same goals.

Personally i am leaning toward style 4

However for on the fly data processing i would recommend style 3 for speed.

Link to comment
Share on other sites

8 answers to this question

Recommended Posts

  • 0

I'd pick style 2 as it's the most simple to understand. There is a certain elegance to writing sophisticated code but when it comes down to it and you're re-reading your code a year later you want to understand every aspect of it as quickly as possible.

 

I used to write cool code, now I just write code that works.

Link to comment
Share on other sites

  • 0

"Style 2" is the sensible thing to do. It's the simplest, fastest, most idiomatic code that achieves what you want to do.

 

By the way, "new" is costly in C++ and must be accompanied by a corresponding delete (which is also costly), otherwise you leak the memory you allocated. Use stack semantics (i.e. local variables, inline objects) in favor of new as much as you can: it's the fast, easy to understand and efficient thing to do. In modern C++ style you almost never use "new", instead you use stack semantics and smart pointers for everything else. So your examples 3, 4 and 5 are absolutely poor style and should be avoided at all costs.

 

"Style 1" seems to introduce an unnecessary variable. Unless you intend to use it after the if statement, it's doesn't need to exist.

 

Also, returning via a pointer or reference argument makes sense only if you want the caller to allocate the data structure, which is pointless for small value types like bools, int, float, etc. It's a common pattern however if the structure is large, i.e.:

SomeLargeStructure s;
InitializeStructure(&s); // ok

bool b;
InitializeBool(&b); // huh? should be "bool b = InitializeBool();"
But actually, even then that pattern is obsolete with C++11. With move semantics, returning by value is the efficient and obvious thing to do for any type. See http://herbsutter.com/elements-of-modern-c-style/
  • Like 2
Link to comment
Share on other sites

  • 0

"Style 2" is the sensible thing to do. It's the simplest, fastest, most idiomatic code that achieves what you want to do.

 

By the way, "new" is costly in C++ and must be accompanied by a corresponding delete (which is also costly), otherwise you leak the memory you allocated. Use stack semantics (i.e. local variables, inline objects) in favor of new as much as you can: it's the fast, easy to understand and efficient thing to do. In modern C++ style you almost never use "new", instead you use stack semantics and smart pointers for everything else.

 

"Style 1" seems to introduce an unnecessary variable. Unless you intend to use it after the if statement, it's doesn't need to exist.

 

Returning via a pointer makes sense only if you want the caller to allocate the data structure, which is pointless for small value types like bools, int, float, etc. It's a common pattern however if the structure is large, i.e.:

SomeLargeStructure s;
InitializeStructure(&s); // ok

bool b;
InitializeBool(&b); // huh? should be "bool b = InitializeBool();"

SomeLargeStructure s;
InitializeStructure(&s); // ok

bool b;
InitializeBool(&b); // huh? should be "bool b = InitializeBool

Yeah your definiatly right, i should only use new when absolutely needed such as buffers and what not.

Link to comment
Share on other sites

  • 0

Also:

 

bool isBigger(int x, int y){
     return ( x > y )? true : false;
}
could be written as:

bool isBigger(int x, int y) {
     return x > y;
}
and then of course calling that function is more complicated than just writing x > y everywhere in code. But that was just an example.
  • Like 1
Link to comment
Share on other sites

  • 0

Unless you have exceptions disabled I would recommend never using:

 

error_code_t fn(T in, U* out)
{
*out = 1;
return SUCCESS;
}

 

Best to just return what you need to and throw an exception if something goes wrong.

If you need to return multiple values, use a struct, std::pair or std::tuple. There really is no need for out parameters any more.

Link to comment
Share on other sites

  • 0

Unless you have exceptions disabled I would recommend never using:

error_code_t fn(T in, U* out)
{
*out = 1;
return SUCCESS;
}

Best to just return what you need to and throw an exception if something goes wrong.

If you need to return multiple values, use a struct, std::pair or std::tuple. There really is no need for out parameters any more.

Depending on what you are doing there are SEVERAL reasons to use out especially in C++, (but not for common means for simple applications).

Link to comment
Share on other sites

  • 0

Depending on what you are doing there are SEVERAL reasons to use out especially in C++, (but not for common means for simple applications).

 

When? With tuple, RVO, NRVO and move semantics I doubt there would ever be a need to assign an object to an out parameter.

Modifying an input parameter passed by reference is fine. For example pass a std::vector to a function and have it populated with certain items. This avoids the memory allocation of returning a new vector to be merged with an existing vector.

 

Side effects make understanding programs difficult, inhibit the ability for compilers to optimise and make developing parallelisable functional algorithms impossible. Returning a value using the return mechanism in most cases makes the most sense.

Link to comment
Share on other sites

  • 0

When? With tuple, RVO, NRVO and move semantics I doubt there would ever be a need to assign an object to an out parameter.

Modifying an input parameter passed by reference is fine. For example pass a std::vector to a function and have it populated with certain items. This avoids the memory allocation of returning a new vector to be merged with an existing vector.

 

Side effects make understanding programs difficult, inhibit the ability for compilers to optimise and make developing parallelisable functional algorithms impossible. Returning a value using the return mechanism in most cases makes the most sense.

 

In cases where you need to do large arithmetic calculations an out parameter is necessary especially when using multiple values.

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.