Some days ago, while reading Standard C++ news I've read the post about Defaulted functions in C++11, in that article is mentioned that the user-defined constructor is less efficient than the one generated by the compiler:
The user-defined default constructor is less efficient than the compiler implicitly defined default constructor.
Continuing the reading, there's an example where an user-defined constructor is marked as default, and then says:
the explicitly defaulted constructor is more efficient than a manually programmed default constructor.
I don't understand these assertions, so I was wondering:
Why a user-default constructor (or special member function) would be less efficient than the compiler implicitly defined one?
How is the efficiency improved by explicitly defaulting a constructor (or special member function)?
What guidelines I must follow to choose to default a constructor (or special member function) and how the efficiency affects this decision?
I think a better statement is that a user-defined default constructor MAY be less efficient than a compiler generated out.
For example, when it's generating a default constructor internally the compiler may be able to make assumptions and optimizations that it can't make for a user-defined contstructor (side-effects come to mind).
Also keep in mind that a user-defined default constructor could do totally different work that default-constructing all its members, resulting in it being less efficient (but also more correct). This doesn't seem to be the case in the link you provided however.
And we all know, that if it's written on internet then it is must be right... Wait, do we?
In the article where I found the first assertion of less efficient, the author tells the truth. Though you seem to misinterpret it -- in the example it refers to the hand-crafted ctor uses assignment. For no good reasons, and going against 2 decade old guidelines.
Next instance, same case. (As a practical note I shall add, that for any compiler claiming to have optimizations I expect the same assy output even for that form...)
I see no reason why the proper handwritten ctor would be different from the defaulted one in any ways, including efficiency. OTOH if they are identical why on earth write it? I'm all too happy that compiler makes it for me. And finally I can even control it in some ways I previously could not. Could use more of such functions. ;-)
Related
When should one add the noexcept attribute to a function? i.e. when is the compiler not able to tell a function throws? Should everything be marked or is there a way to tell?
I'm not a fan of premature optimization, and I'm not a fan of premature attribution. I don't know of a way to "profile" the need of noexcept the same way I profile performance when optimizing.
When evaluating where it is necessary, please comment on the most common compilers, e.g. MSVC, GCC, etc.
The C++ Core Guidelines recommends basically use it everywhere that the code doesn't throw. This is mostly important for libraries because code checkers use the functions you call to see if it's noexcept, otherwise you get a cascade of warnings.
That said, the most important recommendations are to make swap, move, and destructors noexcept.
The C++ Core Guidelines also recommends making default constructors noexcept which is great in general, but many patterns (like the pImpl idiom) often allocate memory in their default constructor. Therefore, I generally use noexcept on default constructors (or constructors that only take defaulted parameters), but if I know it can throw I make a point of explicitly marking it nothrow(false).
If you declare a default constructor, copy constructor, assignment operator, move constructor, move operator, or destructor to be =default it's implicitly noexcept. All destructors are also implicitly noexcept.
There's a notion that you can mark something noexcept to mean "if this does throw, go ahead and crash". I find this notion a bit wooly so in my code I mark things that can throw noexcept(false) or leave it unspecified. That's usually stuff that calls new or initializes std containers.
When should one add the noexcept attribute to a function?
Whenever you want to document and enforce that a function never throws.
It is important to recall that a mistake here means there will be a call to std::terminate() instead of propagating the exception. Due to this, it can be a pessimization.
i.e. when is the compiler not able to tell a function throws?
It is the opposite: the compiler has to assume everything throws unless it can prove otherwise (or is told otherwise).
It will be able to prove it when it has the required definitions. For instance, between TUs without LTO, it won't.
I don't know of a way to "profile" the need of noexcept
Like in any other case: you measure with and without.
For most projects, working on enabling LTO is a better way to deal with it.
It would be nice to be able to easily text search in my codebase for places where is constructor of some object called. Here comes pattern bellow. Instead of classical:
Object val( a, b );
It would be nice to use everywhere:
auto val = Object( a, b );
That way I can use simple text search for "Object(" and get list of places where I am calling constructor of Object. It's also less syntacticaly ambiguous and therefore easier to make simple tools to automate some code transformations. It elegantly avoids "most vexing parse" issues too.
My only concern is about possible impact on performance. Is case 2) as fast a as case 1)? (If we can assume that Object has properly defined move constructor and move assignment operator and basic compiler optimizations are enabled.)
Pre C++17, it is possible, although unlikely, that you would get a performance penalty due to an extra copy or move. Even C++98 allowed implementations to remove such copies even if they would produce side-effects, and almost all compilers have implemented this optimization for a long time -- especially in optimized builds.
Post C++-17, copy elision is guaranteed. You aren't even required to have a copy or move constructor for this to work, so you shouldn't see any difference.
I have a basic C++ question which I really should know the answer to.
Say we have some class A with constructor A(int a). What is the difference between:
A test_obj(4);
and
A test_obj = A(4);
?
I generally use the latter syntax, but after looking up something unrelated in my trusty C++ primer I realized that they generally use the former. The difference between these two is often discussed in the context of built-in types (e.g. int a(6) vs int a = 6), and my understanding is that in this case they are equivalent.
However, in the case of user-defined classes, are the two approaches to defining an object equivalent? Or is the latter option first default constructing test_obj, and then using the copy constructor of A to assign the return value of A(4) to test_obj? If it's this second possibility, I imagine there could be some performance differences between the two approaches for large classes.
I'm sure this question is answered somewhere on the internet, even here, but I couldn't search for it effectively without finding questions asking the difference between the first option and using new, which is unrelated.
A test_obj = A(4); conceptually does indeed construct a temporary A object, then copy/move-construct test_obj from the temporary, and then destruct the temporary.
However this process is a candidate for copy elision which means the compiler is allowed to treat it as A test_obj(4); after verifying that the copy/move-constructor exists and is accessible.
From C++17 it will be mandatory for compilers to do this; prior to that it was optional but typically compilers did do it.
Performance-wise these are equivalent, even if you have a non-standard copy constructor, as mandated by copy elision. This is guaranteed since C++17 but permitted and widely present even in compilers conforming to earlier standards.
Try for yourself, with all optimizations turned off and the standard forced into C++11 (or C++03, change the command line in the top right):
https://godbolt.org/g/GAq7fi
Could someone please explain what is meant by the following?
You must define a default constructor if your class defines member variables and has no other constructors. Otherwise the compiler will do it for you, badly.
What are they referring to as "badly"?
From the expansion of that link:
"The reason for this is that if you
have no other constructors and do not
define a default constructor, the
compiler will generate one for you.
This compiler generated constructor
may not initialize your object
sensibly."
Might refer to how new T and new T() differ when there is no ctor provided.
It's good to be sure that the object is created in a known state. Primitive variables won't be set to zero by default, so you could end up with subtle bugs that don't always show up. By initializing the member variables to sensible variables, everything is much more predictable.
The only problem with the default constructor is that it initializes only what the compiler thinks must be initialized, and not what you may think needs to be initialized. Basically, that means that it will invoke initializers for objects with default initializers. It won't set pointers or simple types like int to sane values, etc. If that is sufficient, then the default constructor is not 'bad'. When it is insufficient, it is a bug (in your code) that you did not define the necessary default constructor with the correct initialization.
Take the Google style guide with a grain of salt -- or maybe a truckload of salt.
It is true that the compiler-generated default constructor won't necessarily initialize members that are of built-in types in a meaningful fashion. If you want that done, then yes, its failure to do that is bad. OTOH, if you don't want that done, then its doing it could be somewhat bad (wasteful) as well.
Bottom line: there are times to write your own default ctor, but they tend toward the exception, not the rule. Although there are simple rules of thumb to cover a lot of cases in C++ and will prevent a lot of problems, this really isn't one of them -- here you pretty much do need to know what the compiler-generated ctor will do, and what you want different if you're going to write your own.
In Debug build most compilers fill uninitialized space with some magic values, so that debugging is reliable. And providing custom constructor prevents certain POD optimizations.
In fact, it's a guideline just to make sure people does explicitely make the statement of what is an invalid or default state of any object.
That way, no surprise when reading the code, compared to the actual execution.
However, think that it's a company guideline, that is used to make sure everyone does follow the same rules, that's not a you-must-follow-it-because-google-does-it.
In fact, if you manage to make all your member objects being in valid state when default constructed, or force you to set a constructor, then there is no good reason for such a guideline.
If you have any primitive types as member variables (eg. int, float), then the default ctor will not initialize them. member variables that are a class type will have their default ctor's invoked.
Prefer member initializer lists, so your user supplied ctor may be empty:
class Foo {
int bar;
float baz;
Foo(): bar(0), baz(0.0f) { /* empty ctor body */ }
};
It won't set integers to 0 or pointers to null. It will run default constructors on object of types with constructors.
Some people would call it 'not sensible'.
It just seems a too simplified version of the rules of 3, you should either define yourself or leave the compiler version of
the copy constructor
the assignment operator
the destructor
(Note that by defining yourself a copy constructor, the compiler won't define a default constructor).
The default constructor built by the compiler does 'nothing', it will not even zero the memory occupied by the object
A few times, when refactoring code, I have forgotten to add the explicit keyword when adding a parameter to a previously-parameterless constructor, or removing parameters from a previously multi-parameter constructor. To prevent this, I have gotten in the habit of marking every constructor explicit, no matter no many arguments it has. (Except, of course, those constructors for which I actually want implicit conversion.)
Is there any downside to this? Performance? Compile time?
It doesn't have any downsides. It will be future safe, because in C++0x multi-parameter constructors participate in initializations using multi-element initializer lists and can forbidden to be used in the cases where only implicit conversions apply using explicit.
So if you find out a give multi-parameter constructor does not logically represent the value of your class, I think it's good to make it explicit (example: I would set a container constructor (size_t size, T defaultValue) be explicit, while the constructor of pair, (T first, U second) be set non-explicit).
I'm not sure, but I think it does have some unexpected consequences for the copy constructor to be explicit. Other than that, I think yo're OK.
There will be no runtime performance difference. The compile time difference is likely to be undetectable.
I think there is no harm in declaring all constructors with arguments explicit, except that it might look redundant for those with more than one argument.
If you declare a type with an explicit default constructor, you may have trouble using it with collection types.