Why pass structure to function instead of separate parameters? [duplicate] - c++

This question already has answers here:
C++ using struct arguments for functions instead of multiple arguments?
(6 answers)
Closed 3 years ago.
Let's say you call a function like this:
someFunc( some_int, some_float, false, "whatever text");
This doesn't look good but if alternatively I pass these by a struct / class, it won't look much better, since I will make up the struct on-the-fly like I do with function parameters.
someFunc( FuncParameters( some_int, some_float, false, "whatever text"));
Even if the struct has the parameter names in it's definition, I don't see those when I call it's constructor.
I can do this instead:
FuncParameters func_parameters;
func_parameters.some_int_data = some_int;
func_parameters.some_float_data = some_float;
func_parameters.some_text_data = "whatever text";
someFunc(func_parameters);
But if I forget the bool-data like above, then nothing will complain about it.
So why do people say that "always pass parameters in structure if there are more than X number of parameters? What am I missing?

Using structures instead of separate parameters has several advantages:
You express that data is related. By naming the struct appropriately, you can give a name to this relation.
A struct grouping related data has a chance to be reused elsewhere in your code.
Once you modify the struct (add/remove members), you don't need to adapt parameter lists. This is particularly true if you have calls through multiple functions, where the struct object is simply passed through.
Named members at the call site (soldier.speed = 3.2;) are clearer than simply passing 3.2. This applies even more to bool literals and function calls such as CreateSoldier(3.2, true, false, true).
There are also some things to keep in mind:
How you pass the struct (by value or pointer) has an effect on how much data is copied, and if you have an extra dereference at runtime.
For simple code, creating a struct only to pass it to a function can actually increase the verbosity and reduce readability of your code.
Only in C99 you have compound literals. For older versions of C it's not possible to pass temporary objects, and you need to explicitly declare a variable.
As you noticed, a well designed function can enforce initialization of all parameters; but you don't see the parameter's name at call site. For functions not taking many parameters, this can be mitigated by naming the function appropriately (e.g. SetSpeed(&soldier, 3.2)).

I think one main reason is code readability. You can read in CppCoreGuidelines
Keep the number of function arguments low
Reason Having many arguments opens opportunities for confusion. Passing lots of arguments is often costly compared to alternatives.
...
Grouping arguments into "bundles" is a general technique to reduce the
number of arguments and to increase the opportunities for checking.
Example
void f(int* some_ints, int some_ints_length); // BAD: C style, unsafe
versus
void f(gsl::span<int> some_ints); // GOOD: safe, bounds-checked
With your example
someFunc(10,20,true,"foo");
is more confusing than:
struct SomeFuncParameters
{
int max_iterations = 100;
float epsilon = 1.e-6;
bool reinit = true;
std::string name = "";
};
void someFunc(const SomeFuncParameters& parameters) {}
int main()
{
// Variation 1
//
someFunc(SomeFuncParameters());
// Variation 2
//
someFunc(SomeFuncParameters{.max_iterations = 10,
.epsilon = 1e-4,
.reinit = false,
.name = "my name"});
// Variation 3
//
SomeFuncParameters someFuncParameters;
someFuncParameters.epsilon = 1e-10;
someFunc(someFuncParameters);
}
even if you have to write a longer code.
Also note that when you use a struct to store parameters you can easily define parameter default values. You also have less code to modify if you want to add or remove some parameters as the call sites like:
someFunc(SomeFuncParameters());
someFunc(someFuncParameters);
won't be affected.
I also wrote a small C++17 lib for named optional arguments that can maybe interest you.

Related

Recursive functions with constant parameters

In C++ is there a preferred way of dealing with a recursive function that reuses an unchanged object every time? For example (pseudo code):
void func(HashMap h, Logger logger, int depth)
{
// Do stuff then call func recursively...
func(h, logger, depth+1);
}
So every call we pass in several objects (hash map and logger) unchanged. Yes we can pass by reference but it still seems inefficient and doesn't look very pretty. The only alternative I can think of is global variables or bundling up the constant parameters in a struct.
What you're describing is a closed lexical environment, aka a "closure". That concept exists "for free" in dynamic languages like Lisp and Scheme, where the "let over lambda" pattern allows you to capture variables in a function and use them even though their enclosing scope is gone or exited.
You can simulate closures in C++ using a struct as the container for the captured variables and apply functions (functors) to the struct. The most common pattern for this is typically the way that operator() is used:
struct my_closure {
Hashmap &hmap_;
Logger &logger_;
int depth_;
my_closure(Hashmap &hmap, Logger &logger, int depth) :
hmap_(hmap), logger_(logger), depth_(depth)
{ }
void operator()(void)
{ /* do stuff here, including recurse */ }
};
The only thing this will save you is pushing extra stuff on the stack, which doesn't necessarily save you much in terms of cycles (1 struct reference [this pointer for the struct] vs. 2 references + 1 integer.) If your compiler supports tail recursion, this could be a benefit at the expense of readability.
This is perfectly clean code that expresses exactly what is happening. Of course in C++ you should pass the HashMap and the Logger as const reference.
From a performance point of view, however it might be better to make these two objects class variables. But this could make the code harder to understand, so just do it if you really have a performance issue.
By the way, what is the function doing if it doesn't modify the HashMap and returns void?

Can a recursive function have knowledge of a constant in the function in which it was first called without sending it the constant as a parameter?

Because recursion has the added overhead of pushing and popping activation records, is it possible to avoid this when it comes to using constants?
For example if I have a function
void foo(int x) {
int bar = x;
fooAux(root);
}
fooAux(Root * root) {
// Can I somehow do something with the variable bar here?
// {Insert recursive code}
}
I'm not sure if there's any way other than passing bar into the recursive function but this seems unnecessary as I am certain that its value is not meant to change? Maybe passing by reference could ease the matter? Thoughts, please.
The question is not very clear, referring to a "constant" in the title, but then in the code example using a variable.
Anyway the answer is "yes", a recursive helper function can easily refer to a constant or variable in a non-recursive caller function, as long as thread-safety is not a concern.
All you need to do is declare the variable static:
struct Whatever {};
void foo( int x )
{
static int bar;
struct Aux
{
static void foo( Whatever )
{
(void) bar;
}
};
bar = x;
Aux::foo( Whatever() );
}
Is this a good idea? No, it smells of premature optimization. The speed gain, if any, would be marginal, while the maintenance cost could be high.
You can do this using a global variable, e.g: g_bar.
However, this makes your function neither reentrant or elegant.
You can also create a separate struct consisting of the two functions above and a bar member variable, it would be a nice example of premature optimization of the devil.
If I understand you correctly you question is not primarily about recursion, but about scoping. Maybe you could also live with an answer to: Can a function access a variable which is not passed as a parameter (nor defined locally)
The answer this this question is "yes". There are several options:
A function can have access to global variables. In many cases this is an anti-pattern and not exactly what you are looking for.
There is a very interesting concept of a closure, which comes very close to what you are looking for. It allows a function to access an "environemnt" in which your bar variable could live.
However, there are no closures in C++ and I am not aware of any elegant way of mimicking closures in C++. Also closures where invented for semantic reasons (it gives programmers more power), not for performance reasons.

this-> to reference everything

I've recently spent a lot of time with javascript and am now coming back to C++. When I'm accessing a class member from a method I feed inclined to prefix it with this->.
class Foo {
int _bar;
public:
/* ... */
void setBar(int bar) {
this->_bar = bar;
// as opposed to
_bar = bar;
}
}
On reading, it saves me a brain cycle when trying to figure out where it's coming from.
Are there any reasons I shouldn't do this?
Using this-> for class variables is perfectly acceptable.
However, don't start identifiers with an underscore, or include any identifiers with double underscore __ anywhere. There are some classes of reserved symbols that are easy to hit if you violate either of these two rules of thumb. (In particular, _IdentifierStartingWithACapital is reserved by the standard for compilers).
In principle, accessing members via this-> is a coding style that can help in making things clearer, but it seems to be a matter of taste.
However, you also seem to use prefixing members with _ (underscore). I would say that is too much, you should go for either of the two styles.
Are there any reasons I shouldn't do this?
Yes, there is a reason why you shouldn't do this.
Referencing a member variable with this-> is strictly required only when a name has been hidden, such as with:
class Foo
{
public:
void bang(int val);
int val;
};
void Foo::bang(int val)
{
val = val;
}
int main()
{
Foo foo;
foo.val = 42;
foo.bang(84);
cout << foo.val;
}
The output of this program is 42, not 84, because in bang the member variable has been hidden, and val = val results in a no-op. In this case, this-> is required:
void Foo::bang(int val)
{
this->val = val;
}
In other cases, using this-> has no effect, so it is not needed.
That, in itself, is not a reason not to use this->. The maintennance of such a program is however a reason not to use this->.
You are using this-> as a means of documentation to specify that the vairable that follows is a member variable. However, to most programmers, that's not what usign this-> actually documents. What using this-> documents is:
There is a name that's been hidden here, so I'm using a special
technique to work around that.
Since that's not what you wanted to convey, your documentation is broken.
Instead of using this-> to document that a name is a member variable, use a rational naming scheme consistently where member variables and method parameters can never be the same.
Edit Consider another illustration of the same idea.
Suppose in my codebase, you found this:
int main()
{
int(*fn)(int) = pingpong;
(fn)(42);
}
Quite an unusual construct, but being a skilled C++ programmer, you see what's happening here. fn is a pointer-to-function, and being assigned the value of pingpong, whatever that is. And then the function pointed to by pingpong is being called with the singe int value 42. So, wondering why in the world you need such a gizmo, you go looking for pingpong and find this:
static int(*pingpong)(int) = bangbang;
Ok, so what's bangbang?
int bangbang(int val)
{
cout << val;
return val+1;
}
"Now, wait a sec. What in the world is going on here? Why do we need to create a pointer-to-function and then call through that? Why not just call the function? Isn't this the same?"
int main()
{
bangbang(42);
}
Yes, it is the same. The observable effects are the same.
Wondering if that's really all there is too it, you see:
/* IMPLEMENTATION NOTE
*
* I use pointers-to-function to call free functions
* to document the difference between free functions
* and member functions.
*/
So the only reason we're using the pointer-to-function is to show that the function being called is a free function
and not a member function.
Does that seem like just a "matter of style" to you? Because it seems like insanity to me.
Here you will find:
Unless a class member name is hidden, using the class member name is equivalent to using the class member name with the this pointer and the class member access operator (->).
I think you do this backwards. You want the code to assure you that what happens is exactly what is expected.
Why add extra code to point out that nothing special is happening? Accessing class members in the member functions happen all the time. That's what would be expected. It would be much better to add extra info when it is not the normal things that happen.
In code like this
class Foo
{
public:
void setBar(int NewBar)
{ Bar = NewBar; }
you ask yourself - "Where could the Bar come from?".
As this is a setter in a class, what would it set if not a class member variable?! If it wasn't, then there would be a reason to add a lot of info about what's actually going on here!
Since you are already using a convention to signify that an identifer is a data member (although not one I would recommend), adding this-> is simply redundant in almost all cases.
This is a somewhat subjective question obvously. this-> seems much more python-idiomatic than C++-idiomatic. There are only a handful of cases in C++ where the leading this-> is required, dealing with names in parent template classes. In general if your code is well organized it will be obvious to the reader that it's a member or local variable (globals should just be avoided), and reducing the amount to be read may reduce complexity. Additionally you can use an optional style (I like trailing _) to indicate member variables.
It doesn't actually harm anything, but programmers experienced with OO will see it and find it odd. It's similarly surprising to see "yoda conditionals," ie if (0 == x).

Determining whether a non-object variable is initialized in C++

So, let's say, in a class in C++, I have a variety of member variables. Structs, strings, ints, etc. etc. Could be anything. These variables can or cannot be set by the initialization of the object of this class. Given int a, float b, char c, sometimes all of them or none of them can be set. When they are set, they can be set to any possible value of the variable. I would like to find someway of setting, and determining whether or not a variable has been set without:
1) Lots of casting. I could always create a Data_Value decorator class that has a boolean, and template it to whatever the given variable is. This would require calling a_data_value.value and a_data_value.isInitialized.
2) Lots of extra Boolean variables. I'd rather not have bool a_initialized, bool b_initialized.
What I would really like to do is something like this:
Python add to a function dynamically
in C++, with any and all variables, including primitives. Tall order I know, and I'm fully expecting the pessimistic answer.
You're right. It's impossible to determine at runtime whether a primitive is "set". Some compilers will warn you for some cases of using uninitialized values, but this is not at all guaranteed.
I would use a nullable template. See http://www.codeproject.com/KB/mcpp/CNullable.aspx
Suppose you have
class Bob {
int a;
int b;
double c;
complex<double> d;
Bob () : a(), b(), c(), d() {}
};
When you create a new Bob, everything will be set to default (zero in this case).
There is no set or not set state for primitive types. They always hold some value.
If you want to rewrite Python in C++ you can.
You'd need an efficient unordered_map class keyed by string. The string would be the variable name.
Each variable value would be a class (call it a VARIANT, heh) that can hold any primitive value.
Then instead of a C++ struct you'd make your "struct" be an instance of your unordered_map aka dictionary.
If the variable name is found in the dictionary then it was set and you can return the value. If it isn't found it was never set.
If you plan to reference your dictionary keys by name from within C++ you will want to use the following for efficiency:
Instead of:
VARIANT v = dict["name"];
Use:
static const std::string name_key("name");
VARIANT v = dict[name_key];
That way instead of building a std::string containing "name" for the key lookup every time into the function, it will be done once.

Default parameters with C++ constructors [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Is it good practice to have a class constructor that uses default parameters, or should I use separate overloaded constructors? For example:
// Use this...
class foo
{
private:
std::string name_;
unsigned int age_;
public:
foo(const std::string& name = "", const unsigned int age = 0) :
name_(name),
age_(age)
{
...
}
};
// Or this?
class foo
{
private:
std::string name_;
unsigned int age_;
public:
foo() :
name_(""),
age_(0)
{
}
foo(const std::string& name, const unsigned int age) :
name_(name),
age_(age)
{
...
}
};
Either version seems to work, e.g.:
foo f1;
foo f2("Name", 30);
Which style do you prefer or recommend and why?
Definitely a matter of style. I prefer constructors with default parameters, so long as the parameters make sense. Classes in the standard use them as well, which speaks in their favor.
One thing to watch out for is if you have defaults for all but one parameter, your class can be implicitly converted from that parameter type. Check out this thread for more info.
I'd go with the default arguments, especially since C++ doesn't let you chain constructors (so you end up having to duplicate the initialiser list, and possibly more, for each overload).
That said, there are some gotchas with default arguments, including the fact that constants may be inlined (and thereby become part of your class' binary interface). Another to watch out for is that adding default arguments can turn an explicit multi-argument constructor into an implicit one-argument constructor:
class Vehicle {
public:
Vehicle(int wheels, std::string name = "Mini");
};
Vehicle x = 5; // this compiles just fine... did you really want it to?
This discussion apply both to constructors, but also methods and functions.
Using default parameters?
The good thing is that you won't need to overload constructors/methods/functions for each case:
// Header
void doSomething(int i = 25) ;
// Source
void doSomething(int i)
{
// Do something with i
}
The bad thing is that you must declare your default in the header, so you have an hidden dependancy: Like when you change the code of an inlined function, if you change the default value in your header, you'll need to recompile all sources using this header to be sure they will use the new default.
If you don't, the sources will still use the old default value.
using overloaded constructors/methods/functions?
The good thing is that if your functions are not inlined, you then control the default value in the source by choosing how one function will behave. For example:
// Header
void doSomething() ;
void doSomething(int i) ;
// Source
void doSomething()
{
doSomething(25) ;
}
void doSomething(int i)
{
// Do something with i
}
The problem is that you have to maintain multiple constructors/methods/functions, and their forwardings.
In my experience, default parameters seem cool at the time and make my laziness factor happy, but then down the road I'm using the class and I am surprised when the default kicks in. So I don't really think it's a good idea; better to have a className::className() and then a className::init(arglist). Just for that maintainability edge.
Sam's answer gives the reason that default arguments are preferable for constructors rather than overloading. I just want to add that C++-0x will allow delegation from one constructor to another, thereby removing the need for defaults.
Either approach works. But if you have a long list of optional parameters make a default constructor and then have your set function return a reference to this. Then chain the settors.
class Thingy2
{
public:
enum Color{red,gree,blue};
Thingy2();
Thingy2 & color(Color);
Color color()const;
Thingy2 & length(double);
double length()const;
Thingy2 & width(double);
double width()const;
Thingy2 & height(double);
double height()const;
Thingy2 & rotationX(double);
double rotationX()const;
Thingy2 & rotatationY(double);
double rotatationY()const;
Thingy2 & rotationZ(double);
double rotationZ()const;
}
main()
{
// gets default rotations
Thingy2 * foo=new Thingy2().color(ret)
.length(1).width(4).height(9)
// gets default color and sizes
Thingy2 * bar=new Thingy2()
.rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
// everything specified.
Thingy2 * thing=new Thingy2().color(ret)
.length(1).width(4).height(9)
.rotationX(0.0).rotationY(PI),rotationZ(0.5*PI);
}
Now when constructing the objects you can pick an choose which properties to override and which ones you have set are explicitly named. Much more readable :)
Also, you no longer have to remember the order of the arguments to the constructor.
One more thing to consider is whether or not the class could be used in an array:
foo bar[400];
In this scenario, there is no advantage to using the default parameter.
This would certainly NOT work:
foo bar("david", 34)[400]; // NOPE
Mostly personal choice. However, overload can do anything default parameter can do, but not vice versa.
Example:
You can use overload to write A(int x, foo& a) and A(int x), but you cannot use default parameter to write A(int x, foo& = null).
The general rule is to use whatever makes sense and makes the code more readable.
If creating constructors with arguments is bad (as many would argue), then making them with default arguments is even worse. I've recently started to come around to the opinion that ctor arguments are bad, because your ctor logic should be as minimal as possible. How do you deal with error handling in the ctor, should somebody pass in an argument that doesn't make any sense? You can either throw an exception, which is bad news unless all of your callers are prepared to wrap any "new" calls inside of try blocks, or setting some "is-initialized" member variable, which is kind of a dirty hack.
Therefore, the only way to make sure that the arguments passed into the initialization stage of your object is to set up a separate initialize() method where you can check the return code.
The use of default arguments is bad for two reasons; first of all, if you want to add another argument to the ctor, then you are stuck putting it at the beginning and changing the entire API. Furthermore, most programmers are accustomed to figuring out an API by the way that it's used in practice -- this is especially true for non-public API's used inside of an organization where formal documentation may not exist. When other programmers see that the majority of the calls don't contain any arguments, they will do the same, remaining blissfully unaware of the default behavior your default arguments impose on them.
Also, it's worth noting that the google C++ style guide shuns both ctor arguments (unless absolutely necessary), and default arguments to functions or methods.
I would go with the default parameters, for this reason: Your example assumes that ctor parameters directly correspond to member variables. But what if that is not the case, and you have to process the parameters before the object is initialize. Having one common ctor would be the best way to go.
One thing bothering me with default parameters is that you can't specify the last parameters but use the default values for the first ones. For example, in your code, you can't create a Foo with no name but a given age (however, if I remember correctly, this will be possible in C++0x, with the unified constructing syntax). Sometimes, this makes sense, but it can also be really awkward.
In my opinion, there is no rule of thumb. Personnaly, I tend to use multiple overloaded constructors (or methods), except if only the last argument needs a default value.
Matter of style, but as Matt said, definitely consider marking constructors with default arguments which would allow implicit conversion as 'explicit' to avoid unintended automatic conversion. It's not a requirement (and may not be preferable if you're making a wrapper class which you want to implicitly convert to), but it can prevent errors.
I personally like defaults when appropriate, because I dislike repeated code. YMMV.