Conversion operators can now be marked
as explicit.
Monday, July 31, 2017
C++11: Override Controls: final
You can declare a function to be final
in a base class, which will prevent any derived class from overriding that
function.
C++11: Override Controls: override
You can tell the compiler that you are attempting
to override a function, so that the compiler can check whether you are really
overriding the function or just overloading the function.
C++11: Inherited Constructors
You can pull Base Class Constructors into a Derived Class’ scope. Here is an example:
#include <iostream> class Base { public: Base(int i) {std::cout << "Base One Parameter CTOR called. ";} }; class Derived : public Base { using Base::Base; // Without this line, the program would not compile. }; int main() { Base base(1) ; Derived derived(1); return 0; } // Output: Base One Parameter CTOR called. Base One Parameter CTOR called.Reference: https://isocpp.org/wiki/faq/cpp11-language-classes#delegating-ctor
C++11: In-class member initializers: non-static data members
Non-static data members can be initialized where they are declared in the class.
Here is an example:
https://isocpp.org/wiki/faq/cpp11-language-classes#member-init
#include <iostream> class A { public: int a = 1; }; int main() { A a; std::cout << a.a << std::endl; return 0; } // Output: 1References: http://en.cppreference.com/w/cpp/language/data_members
https://isocpp.org/wiki/faq/cpp11-language-classes#member-init
C++11: Delegating Constructors
You can now call a constructor from the MIL (Member Initialization List) of another constructor from the same class.
#include <iostream> class A { public: int m_a; A() : A(42) {} A(int a) : m_a(a) {} }; int main() { A a; std::cout << a.m_a << std::endl; return 0; } // Output: 42Reference: https://isocpp.org/wiki/faq/cpp11-language-classes#delegating-ctor
C++11: =delete
Specifying =delete for any of the compiler-generated constructors or assignment operators, makes them unavailable.
Here is an example:
#include <iostream> class A { public: A() {std::cout << "Default CTOR called; ";} A(const A& a) = delete; }; int main() { A a1; // A a2(a1); // This line does not compile because of " = delete' above. return 0; } // Output: Default CTOR calledReference: https://isocpp.org/wiki/faq/cpp11-language-classes#default-delete
C++11: =default
Instead of providing a body for a class constructors or assignment operators, you can specify =default in the declaration.
Here is an example:
#include <iostream> class A { public: A() = default; // Without this line, this file will not compile. A(const A& a) {std::cout << "Copy CTOR called; ";} A& operator=(A& a) { std::cout << "Assignment Operator called; "; return *this; } }; int main() { A a1; A a2(a1); // Copy CTOR called a1 = a2; // Assignment Operator called return 0; } // Output: Copy CTOR called; Assignment Operator called;Reference: https://isocpp.org/wiki/faq/cpp11-language-classes#default-delete
C++11: User-defined Literals: Four Kinds
There are four kinds of user-defined literals: Integer, Floating Point, String, and Char. Here are examples of each one.
#include <iostream> int operator""_type1 (unsigned long long i ) {return 1 ;} // Integer Literal double operator""_type2a(long double d ) {return 2.1;} // Floating-point Literal (Cooked) double operator""_type2b(const char * s ) {return 2.2;} // Floating-point Literal (Raw) const char * operator""_type3 (const char * s, size_t length) {return s ;} // String Literal char operator""_type4 (char c ) {return c ;} // Character Literal int main() { std::cout << 5_type1 << " " << 5.0_type2a << " " << 5.0_type2b << " " << "Hello"_type3 << " " << 'c'_type4 << std::endl; return 0; } // Output: 1 2.1 2.2 Hello cReference: https://isocpp.org/wiki/faq/cpp11-language#udls
C++11: User-defined Literals
A User-defined literal is a constant that has a suffix that a class can define an operator for to handle. Here is an example:
#include <cmath> #include <iostream> int operator ""_z(unsigned long long i) { return (int)std::pow(2, i); } int main() { std::cout << 5_z << std::endl; return 0; } // Output: 32Reference: https://isocpp.org/wiki/faq/cpp11-language#udls
Monday, July 24, 2017
C++11: Inline namespace: transitivity
Inline namespace behavior is transitive.
For example: if you had three nested namspaces and the two inner namespaces
were declared inline, then all of the inner namespaces’ symbols can be seen in
the outer namespace.
C++11: Inline namespace
You can declare a namespace inline. This causes it’s symbols to be accessed as if they were contained in the enclosing namespace. Here is an example:
#include <iostream>
#define BOTTOM_VERSION 1
namespace Top {
#if BOTTOM_VERSION == 1
inline
#endif
namespace Bottom_V1
{
const int v = 1;
}
#if BOTTOM_VERSION == 2
inline
#endif
namespace Bottom_V2
{
const int v = 2;
}
}
int main()
{
std::cout << Top::v << " " <<
Top::Bottom_V1::v << " " <<
Top::Bottom_V2::v << std::endl;
return 0;
}
// Output: 1 1 2
// If BOTTOM_VERSION is #defined as 2, then the output is: 2 1 2
Reference: https://isocpp.org/wiki/faq/cpp11-language#inline-namespace
C++11: Exceptions: current_exception()
You can call current_exception() to get
a pointer to the current exception. The function returns the pointer of the
type exception_ptr.
C++11: nullptr
The nullptr
value is not an int. It’s type is std::nullptr_t.
C++11: nullptr
The preferred way of setting a pointer
to the null pointer is to use the literal nullptr.
C++11: constexpr: object initialization
Marking an object definition to be
constexpr guarantees the initialization will be done at compile-time.
Marking an object definition to be const
does not guarantee the initialization will be done at compile-time.
C++11: constexpr: function declaration
By marking things constexpr, you can use them in initialization that is performed at compile-time.
Here is an example:
#include <iostream>
constexpr int orBits(int bit2, int bit1, int bit0)
{
return int(4 * int(bit2) | int(2 * bit1)+int(bit0));
}
int orBits2(int bit2, int bit1, int bit0)
{
return int(4 * int(bit2) | int(2 * bit1)+int(bit0));
}
int main()
{
int x = 7;
switch (x)
{
case orBits(1, 1, 1):
std::cout << 7 << std::endl;
break;
}
switch (x)
{
// case orBits2(1, 1, 1): // Error: expression did not evaluate to a
// constant.
std::cout << 7 << std::endl;
break;
}
return 0;
}
// Output: 7
Reference: https://isocpp.org/wiki/faq/cpp11-language#cpp11-constexpr
C++11: noexcept: copy and move
It is recommended that copy and move
operations are specified as noexcept.
C++11: noexcept: noexcept(true)
Specifying “noexcept” is equivalent to
specifying “noexcept(true)”.
C++11: noexcept: destructors
A destructor should not throw any
exceptions. Compiler generated
destructors are implicitly marked as noexcept.
Monday, July 17, 2017
C++11: noexcept
The ‘noexcept’ keyword is the preferred
replacement for the ‘throw()’ exception specification.
C++11: Lambda Expressions: Function Objects
Lambda Expressions can be used in place
of function objects. For example, as the comp parameter in the std:: sort()
template function.
template
void sort (RandomAccessIterator first, RandomAccessIterator last,
Compare comp);
References: http://en.cppreference.com/w/cpp/language/lambda
C++11: Lambda Expressions: Capture List
In a lambda expression, “[]” and it’s
contents define the capture list.
The following are some variations of the
capture list:
[] captures nothing
[&] captures all local variables by
reference
[=] captures all local variables by
value
[this] captures the current object by
reference
[a] captures local variable a by copy
[&a] captures local variable a by
reference
Here is an example:
#include
int main()
{
int local1 = 3;
int local2 = 4;
[&](int param1, int param2) {std::cout << param1 <<
" " << param2 << " "
<< local1 << " " << local2 <<
std::endl;}(1, 2);
return 0;
}
// Output: 1 2 3 4
C++11: Lambda Expressions: Parameter Passing
The example below shows how to pass
parameters to a lambda expression.
#include
int main()
{
[](int param1, int param2) {std::cout << param1 << "
" << param2 << std::endl;}(1, 2);
return 0;
}
// Output: 1 2
C++11: Lambda Expressions
Lambda Expressions let you define unnamed
functions. Here is an example:
#include
int main()
{
[]() {std::cout << 1 << std::endl;}();
return 0;
}
// Output: 1
C++11: Perfect Forwarding
This is the ability to wrap a function
without creating all combinations constness overloads. Here is an example:
#include
template
void func(T i)
{
std::cout << i << " ";;
}
template
void
wrapper_without_perfect_forwarding(T& i)
{
func(i);
}
template
void
wrapper_with_perfect_forwarding(T&& i)
{
func(std::forward(i));
}
int main()
{
int variable = 1;
wrapper_without_perfect_forwarding(variable);
// wrapper_without_perfect_forwarding(2); // Error: 'void
wrapper_without_perfect_forwarding(T &)':
// cannot convert argument 1
from 'int' to 'int &'
wrapper_with_perfect_forwarding(variable);
wrapper_with_perfect_forwarding(3);
return 0;
}
// Output: 1 1 3
C++11: Universal Reference
A reference that binds to both lvalues
and rvalues. An example of a Universal Reference is an Rvalue Reference to a
template type parameter. Scott Meyer invented the term, by the C++ committee
prefers the term ‘Forwarding Reference’.
C++11: Reference Collapsing
When the compiler changes ‘references to
references’ into ‘references’ in certain situations.
Example:
Typedef A B;
Typedef B C;
C
var; // Var is type A
--
Typedef A& B;
Typedef B C;
C
var; // Var is type A&
--
Typedef A B;
Typedef B& C;
C
var; // Var is type A&
--
Typedef A& B;
Typedef B& C;
C
var; // Var is type A&
--
Typedef A&& B;
Typedef B&& C;
C
var; // Var is type A&&
--
Reference collapsing can also happen
with decltype specifiers and template type parameters. Reference Collapsing for
References (&) existed pre-C++11.
Reference Collapsing for Rvalue References was added in C++11.
https://www.ibm.com/support/knowledgecenter/en/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/language_ref/reference_collapsing.html
C++11: Rvalue References: Move Constructors
There are two Move Contructors: MyClass(MyClass &&) and MyClass(const MyClass &&).
Here is an example:
http://en.cppreference.com/w/cpp/utility/move
#include
struct MyClass
{
MyClass() {std::cout << "Default CTOR called" << std::endl;}
MyClass(MyClass &&) {std::cout << "Move CTOR called" << std::endl;}
MyClass(const MyClass &&) {std::cout << "Move CTOR2 called" << std::endl;}
};
int main()
{
MyClass myNonConstObject; // Default CTOR called
MyClass const myConstObject; // Default CTOR called
MyClass && myRefToNonConstObject(
[]{MyClass nco; // Default CTOR called
return nco;
}()); // Move CTOR called
MyClass const && myRefToConstObject (
[]{MyClass const co; // Default CTOR called
return co;
}()); // Move CTOR2 called
return 0;
}
Output:
Default CTOR called
Default CTOR called
Default CTOR called
Move CTOR called
Default CTOR called
Move CTOR2 called
--
The following changes to the code and the result of the change.
MyClass() {std::cout << "Default CTOR called" << std::endl;}
//MyClass(MyClass &&) {std::cout << "Move CTOR called" << std::endl;}
MyClass(const MyClass &&) {std::cout << "Move CTOR2 called" << std::endl;}
Compiles
Output:
Default CTOR called
Default CTOR called
Default CTOR called
Move CTOR2 called
Default CTOR called
Move CTOR2 called
--
MyClass() {std::cout << "Default CTOR called" << std::endl;}
MyClass(MyClass &&) {std::cout << "Move CTOR called" << std::endl;}
//MyClass(const MyClass &&) {std::cout << "Move CTOR2 called" << std::endl;}
Does not compile.
Error: attempting to reference a deleted function
--
MyClass() {std::cout << "Default CTOR called" << std::endl;}
MyClass(MyClass &&) {std::cout << "Move CTOR called" << std::endl;}
//MyClass(const MyClass &&) {std::cout << "Move CTOR2 called" << std::endl;}
Compiles.
Output:
Default CTOR called
Default CTOR called
Default CTOR called
Default CTOR called
--
//MyClass() {std::cout << "Default CTOR called" << std::endl;}
MyClass(MyClass &&) {std::cout << "Move CTOR called" << std::endl;}
MyClass(const MyClass &&) {std::cout << "Move CTOR2 called" << std::endl;}
Does not compile.
Error: no appropriate default constructor available.
--
MyClass() {std::cout << "Default CTOR called" << std::endl;}
//MyClass(MyClass &&) {std::cout << "Move CTOR called" << std::endl;}
//MyClass(const MyClass &&) {std::cout << "Move CTOR2 called" << std::endl;}
MyClass(MyClass &&) {std::cout << "Copy CTOR called" << std::endl;}
MyClass(const MyClass &) {std::cout << "Copy CTOR2 called" << std::endl;}
Compiles
Output:
Default CTOR called
Default CTOR called
Default CTOR called
Copy CTOR called
Default CTOR called
Copy CTOR2 called
--
MyClass() {std::cout << "Default CTOR called" << std::endl;}
//MyClass(MyClass &&) {std::cout << "Move CTOR called" << std::endl;}
//MyClass(const MyClass &&) {std::cout << "Move CTOR2 called" << std::endl;}
//MyClass(MyClass &&) {std::cout << "Copy CTOR called" << std::endl;}
MyClass(const MyClass &) {std::cout << "Copy CTOR2 called" << std::endl;}
Compiles
Ouput:
Default CTOR called
Default CTOR called
Default CTOR called
Copy CTOR2 called
Default CTOR called
Copy CTOR2 called
--
MyClass() {std::cout << "Default CTOR called" << std::endl;}
//MyClass(MyClass &&) {std::cout << "Move CTOR called" << std::endl;}
//MyClass(const MyClass &&) {std::cout << "Move CTOR2 called" << std::endl;}
MyClass(MyClass &&) {std::cout << "Copy CTOR called" << std::endl;}
//MyClass(const MyClass &) {std::cout << "Copy CTOR2 called" << std::endl;}
Does not compile
Error: attempting to reference a deleted function
--
//MyClass() {std::cout << "Default CTOR called" << std::endl;}
//MyClass(MyClass &&) {std::cout << "Move CTOR called" << std::endl;}
//MyClass(const MyClass &&) {std::cout << "Move CTOR2 called" << std::endl;}
//MyClass(MyClass &&) {std::cout << "Copy CTOR called" << std::endl;}
//MyClass(const MyClass &) {std::cout << "Copy CTOR2 called" << std::endl;}
Compiles:
Output: None
Reference: https://isocpp.org/wiki/faq/cpp11-language#rvalhttp://en.cppreference.com/w/cpp/utility/move
C++11: Rvalue References
In C++98,
references-to-non-const
can bind to lvalues
references-to-const can
bind to lvalues
references-to-const
can bind to rvalues
In C++11, the following was added:
rvalue_references-to-non-const
can bind to rvalues
rvalue_references-to-const
can bind to rvalues
Here is an example:
int main()
{
int lvalue =
3;
int & xxxxxx_ref_to_non_const_bound_to_lvalue = lvalue;
int const & xxxxxx_ref_to_xxx_const_bound_to_lvalue = lvalue;
// int & xxxxxx_ref_to_non_const_bound_to_rvalue
= 3; // Compile Error
int const & xxxxxx_ref_to_xxx_const_bound_to_rvalue = 3;
// int && rvalue_ref_to_non_const_bound_to_lvalue = lvalue; // Compile Error
// int
const && rvalue_ref_to_xxx_const_bound_to_lvalue = lvalue; // Compile Error
int && rvalue_ref_to_non_const_bound_to_rvalue = 3;
int const && rvalue_ref_to_xxx_const_bound_to_rvalue = 3;
return 0;
}
Monday, July 10, 2017
C++11: Rvalue References: Move
A move() template function tells the compiler to
move from source instead of first copying from source. The source is changed to a "cheap default", i.e., an object that is inexpensive to create and delete. Here is an example:
#include
int main()
{
int i = 3;
int & ri = i;
int j = 4;
int & rj = j;
rj = std::move(ri);
std::cout << rj << std::endl;
return 0;
}
// Output: 3
The move() template function is equivalent to a
static_cast to an rvalue reference type.
References: https://isocpp.org/wiki/faq/cpp11-language#rval; http://en.cppreference.com/w/cpp/utility/move
C++11: Rvalue References
To eliminate a copy of a source object
during construction or assignment, a destination can be defined as an rvalue, so
that a move is made instead of a copy. The symbol for an rvalue reference is
&&. Here is an example:
#include
int main()
{
int&& i = 3;
std::cout << i << std::endl;
return 0;
}
// Output: 3
The above problem doesn’t look too
useful, but imagine that the ‘3’ was an invisible temporary, which is another
form of an rvalue.
C++11: Uniform Initialization: Narrowing Conversions
{} initialization does not allow
narrowing conversions. Here is an example:
int main()
{
unsigned int myUint = { 1}; //
Compiles
unsigned int myUnit2 = {-1}; // Error: requires a narrowing conversion.
return 0;
}
C++11: Initializer lists
You can get the size of an initializer
list with the size() member function. Here is an example:
#include
#include
using namespace std;
int main()
{
initializer_list myInitializer_List;
myInitializer_List = {10, 11, 12};
cout << myInitializer_List.size() << endl;
return 0;
}
// output: 3
C++11: Initializer lists
Initialializer lists must contain
elements of the same type or convertible to the same type of the destination elements.
C++11: range-for: string
A string can be used with a range. Here
is an example:
#include
#include
using namespace std;
int main()
{
string myString = "abc";
for (auto i : myString) cout
<< i << " ";
return 0;
}
// Output: a b c
C++11: range-for: array
An array can be used with a range. Here
is an example:
#include
#include
using namespace std;
int main()
{
int myArray[] = {10, 11, 12};
for (auto i : myArray) cout
<< i << " ";
return 0;
}
// Output: 10 11 12
C++11: range-for: initializer list
An initializer list can be used with a
range. Here is an example:
#include
#include
using namespace std;
int main()
{
for (auto i : {10, 11, 12}) cout << i << " ";
return 0;
}
// Output: 10 11 12
C++11: range-for: standard containers
All standard containers can be used with
a range.
C++11: decltype
decltype’s argument is either a name of
a variable, a name of a type or an expression.
Friday, July 7, 2017
C++11: Initializer Lists
You should prefer constructing objects
with initializer lists over using pre-C++11 constructors that use ‘()’.
C++11: Initializer Lists
An initializer-list constructor is a
constructor that has a single argument of type: std::initializer-list.
C++11: Initializer Lists
Initializer lists used to be limited to
arrays. Now that can be used with any
type.
C++11: range-for
The following are examples of the
‘range-for’ statement:
for (auto element : vector) {}
for (auto& element : vector) {}
for (const auto element : vector) {}
for (const auto& element : vector)
{}
The first returns copies of the vector
elements in the loop, and the second returns references to the vector elements
in the loop. The third and fourth examples are const versions of the first two.
C++11: range-for
The ‘range-for’ statement lets you
iterate through a container that provides begin() and end() iterators.
C++11: decltype
decltype(N) can be used as a type
specifier. The type used is the type of N. For example: int i; decltype(i) j;
declares j to be of type int.
C++11: auto
‘auto ‘ can be used for the type. The type will be
inferred from the initializer. The old meaning of ‘auto’ as a storage specifier
(stack variable) was made illegal.
C++03
C++03 replaced C++98. It consisted
mostly of bug fixes. The most important bug fixed was the specification that
Vector elements where stored contiguous in memory. Most compilers already enforced this. This
requirement allowed compatibility between C++ vectors and C arrays.
Subscribe to:
Posts (Atom)