Showing posts with label cpp_effective_modern_cpp. Show all posts
Showing posts with label cpp_effective_modern_cpp. Show all posts

Feb 16, 2016

[RVO] Details

Conditions for RVO:
iff
(1) the type of the local object is the same as that returned by the function and 
(2) the local object  (i.e not rvalue, but l-value local object is what's being returned.



If the conditions for the RVO are met,
but compilers choose not to perform copy elision, 
the object being returned must be treated as an rvalue.

The situation is similar for by-value function parameters.
They’re not eligible for copy elision with respect to their function’s return value,
but compilers must treat them as rvalues if they’re returned.


clang/g++ command to avoid RVO:

-fno-elide-constructors

reference:
http://stackoverflow.com/questions/13099603/c11-move-constructor-not-called-default-constructor-preferred/13099664#13099664

Sep 16, 2015

[C++] Compiler generated member functions

Compiler generated default:
Destructor:
Compiler will generate default destructor that will call data member's destructor.

Move constructor:
compilers typically generate code to destroy this's data member
in the event that an exception arises inside the move constructor.

Move assignment:
The compiler-generated move assignment operator needs to
destroy this object's data member before
it being reassigned from rhs's data.

Jun 11, 2015

[c++] copy elision

excerpt from EMC++

Widget makeWidget() // as before
{
Widget w;
…
return w;
}
compilers must either elide the copying of w or they must treat the function as if it were written like this:
Widget makeWidget()
{
Widget w;
…
return std::move(w); // treat w as rvalue, because
} // no copy elision was performed
The situation is similar for by-value function parameters. They’re not eligible for copy elision with respect to their function’s return value, but compilers must treat them as rvalues if they’re returned. As a result, if your source code looks like this,
Widget makeWidget(Widget w) // by-value parameter of same
{ // type as function's return
…
return w;
}
compilers must treat it as if it had been written this way:
Widget makeWidget(Widget w)
{
…
return std::move(w); // treat w as rvalue
}

This means that if you use std::move on a local object being returned from a function that’s returning by value, you can’t help your compilers (they have to treat the local object as an rvalue if they don’t perform copy elision), but you can certainly hinder them (by precluding the RVO).

There are situations where applying std::move to a local variable can be a reasonable thing to do (i.e., when you’re passing it to a function and you know you won’t be using the variable any longer), but as part of a return statement that would otherwise qualify for the RVO or that returns a by value parameter isn’t among them.

Sep 17, 2014

[C++11] decltype(auto&&) for forwarding.

Use decltype on auto&& parameters to std::forward them.
[](auto&& arg)
{
 RunMe(std::forward<decltype(arg)>(arg));
}(42);
Reasoning:
if arg is l-value,
auto&& -> auto&&& -> auto&
decltype(arg) -> auto&
thus:
forward<auto&>(arg) -> l-value reference

if arg is r-value,
auto&& -> auto&&
decltype(arg)  -> auto&&
thus:
forward<auto&&>(arg) -> auto&& && -> auto&& -> r-value reverence

------------
i.e
int a;
int& b;
int&& c;

decltype(a) -> int
decltype(b) -> int&
decltype(c) -> int&&

decltype((a)) -> int& , i.e l-value reference
decltype((b)) -> int&& -> int& , i.e l-value reference of l-value reference
decltype((c)) -> int&&& -> int& , i.e l-value reference of r-value reference

[C++11] lambda

"Lambda captures static local variables as reference." 

Jul 14, 2014

[C++11] std::move / std::forward

Quoted from Effective Modern C++:

  • Neither std::move nor std::forward do anything at runtime.
  • Apply std::move to rvalue references and std::forward to universal references the last time each is used.
  • Do the same thing for rvalue references and universal references being returned from functions that return by value.
  • Never apply std::move or std::forward to local objects (including by-value parameters) if they would otherwise be eligible for the return value optimization.
  • Overloading on universal references almost always leads to the universal reference overload being called more frequently than expected.
  • Perfect-forwarding constructors are especially problematic, because they’re typically better matches than copy constructors for non-const lvalues, and they can hijack derived class calls to base class copy and move constructors.
  • Alternatives to the combination of universal references and overloading include the use of distinct function names, passing parameters by (lvalue)-reference-to-const, passing parameters by value, and using tag dispatch.
  • Universal reference parameters often have efficiency advantages, but they also have usability disadvantages.
  • Reference collapsing occurs in four contexts: 
    • template instantiation, 
    • auto type generation, 
    • creation and use of typedefs and alias declarations,
    • decltype.

[C++11] std::unique_ptr / std::shared_ptr

Quote from Effective Modern C++:

For std::unique_ptr, the type of the deleter is part of the
type of the smart pointer, and this makes it possible for compilers to generate
smaller runtime data structures and faster runtime code.
A consequence of this greater efficiency is that pointed-to types must be
complete when compiler generated special functions
(e.g., destructors or move operations) are used.

For std::shared_ptr, the type of the deleter is not part of the type of the smart
pointer. This necessitates larger runtime data structures and somewhat slower
code, but pointed-to types need not be complete when compiler-generated special
functions are employed.

[C++11] STL container, emplacement push_back


Quote from Effective Modern C++:
  • Emplacement functions are often more efficient than their insertion counter parts, and they’re never less efficient.
  • For containers of resource-managing objects, emplacement functions may suffer resource leaks that would not arise through use of insertion functions.
  • Emplacement functions may perform type conversions that would be rejectedby insertion functions.

[C++11] destructor with noexcept

quote from Effective Modern C++:

By default, all memory deallocation functions and all destructors
—both user-defined and compiler-generated—
are implicitly noexcept.

There’s thus no need to declare them noexcept. (Doing so doesn’t hurt anything, it’s just unconventional.)

The only time a destructor is not implicitly noexcept is when a data member of the class (including inherited members and those contained inside other data members) is of a type that expressly states that its destructor may emit exceptions
(e.g., declares it “noexcept(false)”).

Such destructors are uncommon. There are none in the Standard Library.


--------
constexpr , noexcept are part of function interface.
and _Can't_ participate in function overload.