This question already has answers here:
Why should I prefer to use member initialization lists?
(9 answers)
Closed 8 years ago.
I am following two different C++ programming courses. One is a mandatory course from my Physics degree, ROOT-oriented, and one is a course from the Informatics degree I chose on my own.
The problem is, the examples they give for constructors in classes are slightly different.
Let's pick, for example, the default ctor for a class named CDate, containing three ints, one for the day, one for the month, and one for the year. If nothing is passed to initialize the date, it is automatically set to the first of January, 1900.
The slide from the Informatics course gives this example:
CDate::CDate(void){
mDay=1;
mMonth=1;
mYear=1900;
}
While the one from my Physics course gives this:
CDate::CDate():
mDay (1),
mMonth (1),
mYear (1900)
{}
They only put things inside the braces if they have to modify some variables already created outside the braces.
Let's say, for example, we want to create a class representing an histogram, giving the minimum value, the maximum one, the number of bins, and then an array containing the values inside every single bin. The complete constructor would look like this:
histogram::histogram (const int &nBin, const float &min, const float &max):
nBin_p (nBin),
min_p (min),
max_p (max),
binContent_p ( new int[nBin_p] )
{
//initialize to zero the bin content
for (int i = 0; i < nBin_p; ++i)
binContent_p[i] = 0;
}
(the variables with _p are the actual ones of the class, defined as private in the class implementation).
I guess the "better" one is the one by the Informatics, they should know better, right?But still, I wonder, what are in a nutshell the actual differences between the two ways, as slight as they can be? When should I better use one and when the other one, or are they completely equivalent?
The informatics' approach actually sounds very C-derived, they do not take advantage of some C++ "pecularities". They just do some assignments to those member variables.
The physics rather do initialization. At first sight the difference might only seem aesthetic, and probably won't make much of a difference in practice as long as the member variables you are initializing are fundamental types.
But what if you have a member variable that is of an object type and which does not have a void constructor? To invoke a constructor with arguments for that type you can only use the Physics' approach (which is called initialization list, by the way).
The one from your Physics example is called a initialization list, it's the preferred way to initialize member variables. see here for more explanation.
The second syntax is the only option for initializing member object-variables (it's really a constructor call). For simple types, such as int, long, etc., there is only small difference in execution order, which could be always fixed by hand.
Related
I know that c and c++ standards state that if you don't specify first element's value a start value of enum will default to 0.
But e.g. in Linux kernel sources I faced strange declarations dozens of times. e.g. numa_faults_stats:
enum numa_faults_stats {
NUMA_MEM = 0,
NUMA_CPU,
NUMA_MEMBUF,
NUMA_CPUBUF
};
What is the need for explicitly set first element of this enum to 0?
Related post.
There are very many rules for various things in C and C++: this being one of them. Sometimes it's nice to be explicit, for clarity.
Another common one is to use variable names in function prototypes (only the types are needed). Yet another is a return 0; in main in either language. The explicit use of public and private in a C++ class or struct is another.
You can use enums without care its value like only using it comprasions with each other. But sometimes its value is important. You may use is as an index of an array. eg.
struct NUMA Numa[N];
Numa[NUMA_MEM];
Numa[NUMA_CPU];
In this case it is definitly good idea explicitly assing value even it is default equal. You emphasize that its value has usage in code.
This question already has answers here:
What are the advantages of list initialization (using curly braces)?
(5 answers)
Closed 1 year ago.
When I am reading The C++ Programming Language 4th Edition, to initialize a variable, the author said it's better to use {} than = to initialize a variable:
But I see that there are more people use = than {}.
So which method is a good principle to persist? = or {}?
Which one you choose depends on your own coding style and what you think is best. The most important thing is once you decide which method to use, use that method consistently. Don't switch between methods, it can make it very confusing to read your code. An additional style of variable initialization since C++98 (Called "direct initialization") is:
int variable(1)
But I would advise you against doing this, it doesn't work in certain circumstances, as your book may cover.
My personal style is the one my grandfather who worked on IBM mainframes in the 1960's taught me:
int
Variable1 = 2,
Variable2 = 39,
Variable3 = 45;
bool
Foo = true,
Bar = false;
// etc.
You'll notice I use the "=" sign over curly braces too. This seems to be how the majority of people write their code so me and my Grandfather write it that way to reduce confusion when people read our code. How accepted this method is in a corporate setting or in an organization I do not know, I simply thought it was the most attractive and intuitive style. It also saves a lot of typing.
Before any other comes up with the silly idea that
T a = b ( where b is type of T ) ends up in an assignment operator call,
Lets clear it, in C++ and in any object orient language, assignment operator can not be used on a not yet created object.
This is initialization, and this was an invoke of copy constructor all the time, was not matter of C++ version.
In this case the '=' is just a syntactic sugar.
See the Reference in the Explanation section:
The copy constructor is called whenever an object is initialized (by direct-initialization or copy-initialization) from another object of the same type (unless overload resolution selects a better match or the call is elided), which includes
initialization: T a = b; or T a(b);, where b is of type T;
One reason the book suggests using an initializer is that it becomes the initial value.
When using the assignment '=', in some cases you end up constructing the object which gives it an initial value and then the code uses the assignment operator of the class type to change the initial value, so it is less efficient. This is only in some cases, depending on the constructors available and so on.
However, in most cases modern compilers can optimize it to make it the same thing. So it's not worth worrying about.
One problem with C++ is there is always several ways to do the same thing, no matter how simple that thing may be.
I'm still relatively new to C++ and I can't seem to figure out the difference in the following two ways of coding a function that may take one parameter or maybe two or three or more. Anyway, here's my point
function overload:
int aClass::doSomething(int required)
{
//DO SOMETHING
}
int aClass::doSomething(int required, int optional)
{
//DO SOMETHING
}
how is this different to, default value:
int aClass::doSomething(int required, int optional = 0)
{
//DO SOMETHING
}
I know in different circumstances one may be more suitable than another but what kinds of things should I be aware of when choosing between each of these options?
There are several technical reasons to prefer overloading to default arguments, they are well laid out in Google's C++ Style Guide in the Default Arguments section:
Function pointers are confusing in the presence of default arguments,
since the function signature often doesn't match the call signature.
Adding a default argument to an existing function changes its type,
which can cause problems with code taking its address. Adding function
overloads avoids these problems.
and:
default parameters may result in bulkier code since they are
replicated at every call-site -- as opposed to overloaded functions,
where "the default" appears only in the function definition.
On the positive side it says:
Often you have a function that uses default values, but occasionally
you want to override the defaults. Default parameters allow an easy
way to do this without having to define many functions for the rare
exceptions.
So your choice will depend on how relevant the negative issues are for your application.
First off, you're talking about overloading, not overriding. Overriding is done for virtual functions in a derived class. Overloading refers to the same function name with a different signature.
The difference is logical - in the first case (2 versions), the two functions can behave completely different, whereas the second case will have more or less the same logic. It's really up to you.
The compiler doesn't care which of these you use. Imagine that you wrote it as two constructors, and they ended up about 20 lines long. Further imagine that 19 of the lines were identical, and the different line read
foo = 0;
in one version and
foo = optional;
in the other. In this situation, using an optional parameter makes your code far more readable and understandable. In another language, that didn't have optional parameters, you'd implement this by having the one-parameter version call the two parameter version and pass zero to it as the second parameter.
Now imagine a different pair of constructors or functions that again are about 20 lines long but are entirely different. For example the second parameter is an ID, and if it's provided, you look stuff up in the database and if it's not you set values to nullptr, 0, and so on. You could have a default value (-1 is popular for this) but then the body of the function would be full of
if (ID == -1)
{
foo = 0;
}
else
{
foo = DbLookup(ID);
}
which could be hard to read and would make the single function a lot longer than the two separate functions. I've seen functions with one giant if that eseentially split the whole thing into two separate blocks with no common code, and I've seen the same condition tested 4 or 5 times as a calculation progresses. Both are hard to read.
That's the thing about C++. There are lots of ways to accomplish most things. But those different ways serve different purposes, and once you "get" the subtle differences, you will write better code. In this case "better" means shorter, faster (all those ifs cost execution time), and more expressive - people reading it can understand your intentions quickly.
You are making use of the overloading feature, if you provide several constructors. The advantage in this case is, that you can react differently in every constructor on the passed arguments. If that is of importance use overloading.
If you can provide decent default values for your parameters and these wouldn't affect the proper running of your code, use default parameters.
See here for a thread on SO.
I have really heavy task to achieve and I haven't found any solution good enough. So, here is the description:
- task is to evaluate multiple single dimension arrays which number can vary
- good news is that it is possible to specify types of arrays
And desirable way of doing it:
- creating a class with constructor that accepts variable number of arrays
- these arrays should be also used as properties (private members), so multiple operations can be done on(with) them during lifecycle of object
How I tried to do it:
- constructor member function with variable number of paramaters (I'm not sure why this doesn't work)
- constructor with vector should be better way, but how to store arrays that type is specified in separate array, meaning you can't expect certain datatype for certain array in advance
- I tried to declare variable number of arrays as private members with preprocessor, but it seems loops and other code do not work well inside private: declaration
Any idea from anybody?
constructor that accepts variable number of arrays:
vector< vector<T> > ?
the inner vectors can be of different sizes but must be of the same type.
constructor member function with variable number of parameters
You can use a function with variable number of parameters that creates a class, look at how boost::bind works, that takes lots of different parameter lists.
boost mpl may answer what you are trying to do, although it is rather unclear.
Why not use a simple parametrized class ?
If your compiler support C++0x you can also use initializer list for constructors with variable number of paramaters.
template<class ArrayType>
class ArrayContainer
{
std::vector<ArrayType> m_arrays;
public:
ArrayContainer(std::initializer_list<ArrayType> arrays)
{
m_arrays.reserve(arrays.size());
std::copy(arrays.begin(), arrays.end(), m_array);
}
};
The constructor now accepts variable number of arrays.
auto container = new ArrayContainer({ a, b, c });
A similar question was previously asked, but none of the answers really provided what I was looking for.
I am having trouble deciding where consts should be located in a function. I know a lot of people put them at the top, but if you put them as close as possible to where they are used, you'll reduce code span. I.e.
void f() {
const FOO = 3;
...// some code
if ( bar > FOO ) {
...// do stuff
}
}
or
void f() {
...// some code
const FOO = 3;
if ( bar > FOO ) {
...// do stuff
}
}
I'm leaning towards using the const at the top in small functions, and keeping the span as close as possible in large functions, but I was wondering what others' styles/thoughts are regarding this.
At the lowest scope possible, and directly before their first use.
As a matter of style, exceptions can be made for clarity/asthetics, e.g., grouping conceptually similar constants.
Many times, const values are placed at the top of the file so that they are easily recognizable (and "findable") to individuals doing development. However, if you only need a const value for a very small piece of code, it would be better for it to be scoped to only where it is needed as you suggested.
I recommend putting them in the header file under a namespace or class.
Your approach sounds about right.
I even put these magic numbers at the top of a file sometime, to make sure any "settings" or tweakables are highly visible to others.
It depends on what you really want to do. I usually put them very close where they are actually used.
I put them on top when they are grouped and in order to make sense of one you have to look at the others (for instance when a constant depends on another constant).
Especially if you are going to code some longer algorithm having all start values (including const values) and variables declared at the top of the function makes for a lot more clarity when reading the algorithm itself.
In pre-C99 versions of C, you could only define variables at the beginning of blocks. Consequently, the second alternative was not valid C code. I believe that Code Complete favors putting the declaration as close as possible to the first use, but some would have argued against that rule on the grounds making it makes things inconsistent between C and C++.
Now that both standard C and C++ allow you to move the declaration close to the first usage, that objection no longer holds.
There are times when there are compelling reasons why putting the declaration as late as possible is better for non-const variables than at the top. For example, a declaration without an initialization opens up the possibility of accidentally reading an uninitialized variable. Furthermore, in C++, declaring a class variable at the top of the function with no initialization invokes the default constructor. When it's later assigned, it invokes the assignment operator. If the variable were instead declared at the point of initialization, that invokes the copy constructor. The cost of a default constructor + assignment can often be larger than the cost of the copy constructor.
This last argument can only apply to non-const variables, obviously, since there is no assignment on a const variable. But, why would you want to have to look in a different place for your const declarations? And if const int n=3; is obviously const, what about const char *s = "FOO";? Is that const enough to belong at top or not? Or does it have to be const char * const s = "FOO";? Also, what if you don't yet know what value you want your const variable initialized to at the top, then you must postpone declaring your const variable until you know what it needs to be initialized to.