730 likes | 757 Vues
Modern C++ tips & tricks. Kamil Szatkowski, kamil.szatkowski@nokia.com Łukasz Ziobroń , lukasz.ziobron@nokia.com 201 6 - 11 - 15. About authors. Kamil Szatkowski Work @ Nokia: C++ software engineer @ CCH C ++ software engineer @ LTE CPlane Code Reviewer Trainer:
E N D
Modern C++ tips & tricks Kamil Szatkowski, kamil.szatkowski@nokia.com Łukasz Ziobroń, lukasz.ziobron@nokia.com 2016-11-15
About authors Kamil Szatkowski • Work @ Nokia: • C++ software engineer @ CCH • C++ software engineer @ LTE CPlane • Code Reviewer • Trainer: • PARO 2015, PARO 2016 • Nokia Academy • Speaker: • AMPPZ 2015 • code::dive community • code::dive 2016 • Blogger: • netrix.org.pl Łukasz Ziobroń • Work @ Nokia: • C++ software engineer @ LTE Cplane • Python developer @ LTE LOM • C++ software engineer @ LTE OAM • Scrum Master • Trainer: • PARO 2015, PARO 2016 • Nokia Academy • Speaker: • AMPPZ 2015 • code::dive community • code::dive 2015 • code::dive 2016 • Blogger: • ziobron.net
C++ standarization history Introduction to C++ standards • 1998 – first ISO C++ standard • 2003 - TC1 (“Technical Corrigendum 1”) published as (“C++03”). Bug fixes for C++98 • 2005 - “Technical Report 1” published • 2011 – ratified C++0x -> C++11 • 2013 – full version of C++14 draft • 2014 - C++14 published (minor revision) • 2017? – big standard modification planned as C++17
Compilers support C++11 support Selected features fromC++11 -gcc4.3, clang2.9 Full support- gcc4.6, clang3.3 Compiler flag: -std=c++0x -std=c++11 –sincegcc4.7, clang3.3 More details: http:://gcc.gnu.org/projects/cxx0x.html http://clang.llvm.org/cxx_status.html C++14 support Basic functionality- gcc4.9, clang3.3 Full support – gcc5, clang3.4 Compiler flag: -std=c++1y -std=c++14 More details: http:://gcc.gnu.org/projects/cxx1y.html http://clang.llvm.org/cxx_status.html Introduction to C++ standards
Question1 Which of the following keywords were introduced in C++11? • constexpr • decltype • noexcept • NULL • auto
Question 1 Which of the following keywords were introduced in C++11? • constexpr • decltype • noexcept • NULL • auto • Answers: A, B, C
Question 2 Passing empty pointer to bar function: bar(nullptr); Which of its overloaded version will be called? • void bar(int); • void bar(void*); • void bar(nullptr_t);
Question 2 Passing empty pointer to barfunction: bar(nullptr); Which of its overloaded version will be called? • void bar(int); • void bar(void*); • void bar(nullptr_t); Answer: C, but if it doesn’t exist then B.
Question 3 What is the type of variable something? auto something = {1}; • int • std::initializer_list<int> • std::array<int, 5> • int[]
Question 3 What is the type of variable something? auto something = {1}; • int • std::initializer_list<int> • std::array<int, 5> • int[] Answer: B, but from C++17 it will be A
Question 4a What will be the result of the following code? template<class T> void foo(T v) { std::cout << v << std::endl; } foo({1,2,3,4,5});
Question 4a What will be the result of the following code? template<class T> void foo(T v) { std::cout << v << std::endl; } foo({1,2,3,4,5}); Answer: This code will not compile: error: no matching function for call to 'foo(<brace-enclosed initializer list>)'
Question 4b What will be the result of the following code? template<class T> void foo(T v) { std::cout << v << std::endl; } auto v = {1,2,3,4,5}; foo(v);
Question 4b What will be the result of the following code? template<class T> void foo(T v) { std::cout << v << std::endl; } auto v = {1,2,3,4,5}; foo(v); Answer: This code will not compile: error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'std::initializer_list<int>')
Question 5 Will it compile? int array[] = { 1, 2, 5.5 };
Question 5 Will it compile? int array[] = { 1, 2, 5.5 }; Answer: C++98 - OK, C++11: error - implicit type narrowing.
Question 6 Are following lines of code correct? std::array<int, 3> a1{1, 2, 3}; std::array<int, 3> a2 = {1, 2, 3};
Question 6 Are following lines of code correct? std::array<int, 3> a1{1, 2, 3}; std::array<int, 3> a2 = {1, 2, 3}; Answer: First is correct in C++14. In C++11 following code is required: std::array<int, 3> a1{ {1, 2, 3} }; Second line of code is correct in both versions of standard.
Question 7 What will happen? intmain() { intitem(); item = 5; std::cout << item; }
Question 7 What will happen? intmain() { intitem(); item = 5; std::cout << item; } Answer: It won’t compile – most vexing parse. error: assignment of function 'int item()' This statement cannot be used in C++ version <11. In C++ >=11 it should be: int item{}
Question 8a What isthe type of g1? Gadget items[10]; auto g1 = items;
Question 8a What is the type ofg1? Gadget items[10]; auto g1 = items; Answer: Gadget*
Question 8b What is the type ofg2? Gadget items[10]; auto & g2= items;
Question 8b What is the type ofg2? Gadget items[10]; auto & g2= items; Answer: Gadget(&)[10]
Question 9 What is wrong with this code? std::map<int, std::string> m; // ... filling m ... for(std::pair<int, std::string> const& elem: m) cout << elem.first << " -> " << elem.second << endl;
Question 9 What is wrong with this code? std::map<int, std::string> m; // ... filling m ... for(std::pair<int, std::string> const& elem: m) cout << elem.first << " -> " << elem.second << endl; Answer: The key type in map is const. Correct code: std::map<int, std::string> m; // ... filling m ... for(auto const& elem: m) // for(std::pair<const int, std::string> const& elem: m) cout << elem.first << " -> " << elem.second << endl;
Question 10 Will it work or not? auto get_name(int id) { if (id == 1) return "Gadget"s; else if (id == 2) return "SuperGadget"s; return string("Unknown"); }
Question 10 Will it work or not? auto get_name(int id) { if (id == 1) return "Gadget"s; else if (id == 2) return "SuperGadget"s; return string("Unknown"); } Answer: Yes, in C++14 – automatic return type deduction.
Question 11a What will happen? struct AAAAA { static const int VALUE = 213; }; std::cout << AAAAA::VALUE << std::endl;
Question 11a What will happen? struct AAAAA { static const int VALUE = 213; }; std::cout << AAAAA::VALUE << std::endl; Answer: It will print 213.
Question 11b What will happen? struct AAAAA { static const int VALUE = 213; }; std::cout << &AAAAA::VALUE << std::endl;
Question 11b What will happen? struct AAAAA { static const int VALUE = 213; }; std::cout << &AAAAA::VALUE << std::endl; Answer: Linking error: undefined reference to `AAAAA::VALUE' Value AAAAA::VALUE is not defined anywhere. It must be defined in one of translations unit as const int AAAAA::VALUE.
Question 12 Will following code compile? constexpr int max(int a, int b) { if(a > b) return a; else return b; }
Question 12 Will following code compile? constexpr int max(int a, int b) { if(a > b) return a; else return b; } Answer: Not in C++11, but in C++14 it will. In C++11 it should be written as follows: constexpr int max(int a, int b) { return a > b ? a : b; }
Question 13a Followingcodeisprovided: struct Foo { void talk() const& {cout << „talk const&” << endl;} void talk() const&& {cout << „talk const&&” << endl;} void talk() & {cout << „talk &” << endl;} void talk() && {cout << „talk &&” << endl;} }; decltype(auto) declFoo() { Foo f; return f; } declFoo().talk(); // in main What will happen?
Question 13a Followingcodeisprovided: struct Foo { void talk() const& {cout << „talk const&” << endl;} void talk() const&& {cout << „talk const&&” << endl;} void talk() & {cout << „talk &” << endl;} void talk() && {cout << „talk &&” << endl;} }; decltype(auto) declFoo() { Foo f; return f; } declFoo().talk(); // in main What will happen? Answer: talk &&
Question 13b Followingcodeisprovided: struct Foo { void talk() const& {cout << „talk const&” << endl;} void talk() const&& {cout << „talk const&&” << endl;} void talk() & {cout << „talk &” << endl;} void talk() && {cout << „talk &&” << endl;} }; decltype(auto) declBar() { Foo f; return(f); } declBar().talk(); // in main What will happen?
Question 13b Followingcodeisprovided: struct Foo { void talk() const& {cout << „talk const&” << endl;} void talk() const&& {cout << „talk const&&” << endl;} void talk() & {cout << „talk &” << endl;} void talk() && {cout << „talk &&” << endl;} }; decltype(auto) declBar() { Foo f; return(f); } declBar().talk(); // in main What will happen? Answer: talk &
Question 14 Is this code correct? struct A { void bar() const final {} }; struct B : A { void bar() const {} };
Question 14 Is this code correct? struct A { void bar() const final {} }; struct B : A { void bar() const {} }; Answer: No. bar()is not virtual. error: 'void A::bar() const' marked 'final', but is not virtual
Question 15 Which overridespecifiers are used correctly? struct A{ virtual void foo() = 0; void dd() {} }; struct B : A{ void foo() override {} void bar() override {} void dd() override {} }
Question 15 Which overridespecifiers are used correctly? struct A{ virtual void foo() = 0; void dd() {} }; struct B : A{ void foo() override {} void bar() override {} void dd() override {} } Answer: Only for foo(),bar() doesn’t exist in base class, dd() is not virtual.
Question 16 Is there a difference? auto x = std::make_shared<std::string>("hello, world!"); std::shared_ptr<std::string> y{new std::string("hello, world!")};
Question 16 Is there a difference? auto x = std::make_shared<std::string>("hello, world!"); std::shared_ptr<std::string> y{new std::string("hello, world!")}; Answer: Yes. std::make_sharedis faster. Allocation of std::string and inner reference counters is in one continuous memory segment. Usage of new can be slower because there is no guaranty of memory continuity for value and reference counters.
Question 17 Considerfollowingcode (C++14): auto a = std::make_shared<int>(1); auto b = std::make_unique<int>(2); template<class A> void foo(A a) { /**/ } Whichline will not compile? A. foo(a); B. foo(b); C. foo(std::move(a)); D. foo(std::move(b));
Question 17 Considerfollowingcode (C++14): auto a = std::make_shared<int>(1); auto b = std::make_unique<int>(2); template<class A> void foo(A a) { /**/ } Whichline will not compile? A. foo(a); B. foo(b); C. foo(std::move(a)); D. foo(std::move(b)); Answer: B. Trivial
Question 18 Whichline will not compile? A. [](){}; B. []{}; C. {}; D. [](); E. []; F. (); G. [](){}();
Question 18 Whichline will not compile? A.[](){}; B.[]{}; C.{}; D.[](); E.[]; F.(); G.[](){}(); Answer: D, E, F won’t compile. A i B are correct lambdas. C are scope braces, which do nothing. G is a correct lambda called after definition.
Question 19 Which lambda function is correct? • []() -> int { return 4; }; • int [](){ return 4; }; • auto [](){ return 4; }; • []() -> auto {return 4; }; • [](){ return 4; }; • []{ return 4; }; • [] -> int { return 4; }; • int []{ return 4; };