Demystifying Value Categories in C++ Icsc 2020
Total Page:16
File Type:pdf, Size:1020Kb
Demystifying Value Categories in C++ iCSC 2020 Nis Meinert Rostock University Disclaimer Disclaimer → This talk is mainly about hounding (unnecessary) copy ctors → In case you don’t care: “If you’re not at all interested in performance, shouldn’t you be in the Python room down the hall?” (Scott Meyers) Nis Meinert – Rostock University Demystifying Value Categories in C++ 2 / 100 Table of Contents PART I PART II → Understanding References → Dangling References → Value Categories → std::move in the wild → Perfect Forwarding → What Happens on return? → Reading Assembly for Fun and → RVO in Depth Profit → Perfect Backwarding → Implicit Costs of const& Nis Meinert – Rostock University Demystifying Value Categories in C++ 3 / 100 PART I Understanding References Q: What is the output of the programs? 1 #!/usr/bin/env python3 1 #include <iostream> 2 2 3 class S: 3 struct S{ 4 def __init__(self, x): 4 int x; 5 self.x = x 5 }; 6 6 7 def swap(a, b): 7 void swap(S& a, S& b) { 8 b, a = a, b 8 S& tmp = a; 9 9 a = b; 10 if __name__ == '__main__': 10 b = tmp; 11 a, b = S(1), S(2) 11 } 12 swap(a, b) 12 13 print(f'{a.x}{b.x}') 13 int main() { 14 S a{1}; S b{2}; 15 swap(a, b); 16 std::cout << a.x << b.x; 17 } godbolt.org/z/rE6Ecd Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 4 / 100 Q: What is the output of the programs? A: 12 A: 22 1 #!/usr/bin/env python3 1 #include <iostream> 2 2 3 class S: 3 struct S{ 4 def __init__(self, x): 4 int x; 5 self.x = x 5 }; 6 6 7 def swap(a, b): 7 void swap(S& a, S& b) { 8 b, a = a, b 8 S& tmp = a; 9 9 a = b; 10 if __name__ == '__main__': 10 b = tmp; 11 a, b = S(1), S(2) 11 } 12 swap(a, b) 12 13 print(f'{a.x}{b.x}') 13 int main() { 14 S a{1}; S b{2}; 15 swap(a, b); 16 std::cout << a.x << b.x; 17 } godbolt.org/z/rE6Ecd Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 4 / 100 Q: What is the output of the program? 1 #include <iostream> 2 3 struct S{ 4 int x; 5 }; 6 7 void swap(S& a, S& b) { 8 S tmp = a; 9 a = b; 10 b = tmp; 11 } 12 13 int main() { 14 S a{1}; S b{2}; 15 swap(a, b); 16 std::cout << a.x << b.x; 17 } godbolt.org/z/r6oq55 Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 5 / 100 A: 21 1 #include <iostream> 2 3 struct S{ 4 int x; 5 }; 6 7 void swap(S& a, S& b) { 8 S tmp = a; 9 a = b; 10 b = tmp; 11 } 12 13 int main() { 14 S a{1}; S b{2}; 15 swap(a, b); 16 std::cout << a.x << b.x; 17 } godbolt.org/z/r6oq55 Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 5 / 100 Q: What is the output of the program? 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S& a, S& b) { 11 S& tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; 18 swap(a, b); 19 std::cout << a.x << b.x; 20 } godbolt.org/z/jfM6h1 Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 6 / 100 A: aacc22 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S& a, S& b) { 11 S& tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; 18 swap(a, b); 19 std::cout << a.x << b.x; 20 } godbolt.org/z/jfM6h1 Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 6 / 100 Q: What is the output of the program? 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S& a, S& b) { 11 S tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; 18 swap(a, b); 19 std::cout << a.x << b.x; 20 } godbolt.org/z/ohe3Wb Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 7 / 100 A: aabcc21 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S& a, S& b) { 11 S tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; 18 swap(a, b); 19 std::cout << a.x << b.x; 20 } godbolt.org/z/ohe3Wb Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 7 / 100 Q: What is the output of the program? 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S* a, S* b) { 11 S* tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; 18 swap(&a, &b); 19 std::cout << a.x << b.x; 20 } godbolt.org/z/8fovsa Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 8 / 100 A: aa12 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S* a, S* b) { 11 S* tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; 18 swap(&a, &b); 19 std::cout << a.x << b.x; 20 } godbolt.org/z/8fovsa Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 8 / 100 Q: What is the output of the program? 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S* a, S* b) { 11 S* tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; S* a_ptr = &a; S* b_ptr = &b; 18 swap(a_ptr, b_ptr); 19 std::cout << a_ptr->x << b_ptr->x; 20 } godbolt.org/z/6357rq Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 9 / 100 A: aa12 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S* a, S* b) { 11 S* tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; S* a_ptr = &a; S* b_ptr = &b; 18 swap(a_ptr, b_ptr); 19 std::cout << a_ptr->x << b_ptr->x; 20 } godbolt.org/z/6357rq Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 9 / 100 Q: What is the output of the program? 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S*& a, S*& b) { 11 S* tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; S* a_ptr = &a; S* b_ptr = &b; 18 swap(a_ptr, b_ptr); 19 std::cout << a_ptr->x << b_ptr->x; 20 } godbolt.org/z/dEsxEY Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 10 / 100 A: aa21 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S*& a, S*& b) { 11 S* tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; S* a_ptr = &a; S* b_ptr = &b; 18 swap(a_ptr, b_ptr); 19 std::cout << a_ptr->x << b_ptr->x; 20 } godbolt.org/z/dEsxEY Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 10 / 100 Q: What is the output of the program? 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S*& a, S*& b) { 11 S* tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; 18 swap(&a, &b); 19 std::cout << a.x << b.x; 20 } godbolt.org/z/Eh656x Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 11 / 100 Q: What is the output of the program? error: cannot bind non-const lvalue reference of type “S*&” to an rvalue of type “S*” 1 #include <iostream> 2 3 struct S{ 4 int x; 5 S(int x): x(x) { std::cout << 'a';} 6 S(const S& other): x(other.x) { std::cout << 'b';} 7 S& operator=(const S& other) { x = other.x; std::cout << 'c'; return *this;} 8 }; 9 10 void swap(S*& a, S*& b) { 11 S* tmp = a; 12 a = b; 13 b = tmp; 14 } 15 16 int main() { 17 S a{1}; S b{2}; 18 swap(&a, &b); 19 std::cout << a.x << b.x; 20 } godbolt.org/z/Eh656x Nis Meinert – Rostock University Demystifying Value Categories in C++ – Understanding References 11 / 100 Value Categories Value categories with Venn diagrams (diagrams shamelessly stolen from bajamircea.github.io/coding/cpp/2016/04/07/move-forward.html) Nis Meinert – Rostock University Demystifying Value Categories in C++ – Value Categories 12 / 100 Value categories with Venn diagrams (diagrams shamelessly stolen from bajamircea.github.io/coding/cpp/2016/04/07/move-forward.html)