From b7dc636c14d712e6bf1c35e1fb7af2f4471d3fc0 Mon Sep 17 00:00:00 2001 From: Light-City <455954986@qq.com> Date: Sun, 15 Dec 2019 16:34:05 +0800 Subject: [PATCH] update --- README.md | 7 +- modern_C++_30/.CMakeLists.txt.un~ | Bin 9012 -> 9976 bytes modern_C++_30/CMakeLists.txt | 6 + modern_C++_30/CMakeLists.txt~ | 14 +++ modern_C++_30/reference/collapses.cpp | 53 +++++++++ .../reference/don'treturnReference.cpp | 55 +++++++++ modern_C++_30/reference/forward.cpp | 45 ++++++++ modern_C++_30/reference/lifetime.cpp | 108 ++++++++++++++++++ modern_C++_30/reference/reference.cpp | 43 +++++++ 9 files changed, 330 insertions(+), 1 deletion(-) create mode 100644 modern_C++_30/CMakeLists.txt~ create mode 100644 modern_C++_30/reference/collapses.cpp create mode 100644 modern_C++_30/reference/don'treturnReference.cpp create mode 100644 modern_C++_30/reference/forward.cpp create mode 100644 modern_C++_30/reference/lifetime.cpp create mode 100644 modern_C++_30/reference/reference.cpp diff --git a/README.md b/README.md index 97de94b..f84e775 100644 --- a/README.md +++ b/README.md @@ -129,11 +129,16 @@ for(decl:col) { - [堆](./modern_++_30/RAII/heap.cpp) - [栈](./modern_C++_30/RAII/stack.cpp) - [RAII](./modern_C++_30/RAII/RAII.cpp) - - [自己动手,实现C++的智能指针](./modern_C++_30/smart_ptr) - [auto_ptr、scope_ptr](./modern_C++_30/smart_ptr/auto_scope.cpp) - [unique_ptr](./modern_C++_30/smart_ptr/unique_ptr.cpp) - [shared_ptr](./modern_C++_30/smart_ptr/shared_ptr.cpp) +- [右值和移动究竟解决了什么问题?](./modern_C++_30/reference) + - [左值与右值](./modern_C++_30/reference/reference.cpp) + - [延长声明周期](./modern_C++_30/reference/lifetime.cpp) + - [引用折叠](./modern_C++_30/reference/collapses.cpp) + - [完美转发](./modern_C++_30/reference/forward.cpp) + - [不要返回本地变量的引用](./modern_C++_30/reference/don'treturnReference.cpp) ### 4.拓展部分 diff --git a/modern_C++_30/.CMakeLists.txt.un~ b/modern_C++_30/.CMakeLists.txt.un~ index b182f804efd53c73ee1c754c87692d2366969cef..b819a9466e0ac043b53e0247c354ec97f09f5410 100644 GIT binary patch delta 367 zcmdnu_QSV6EHih0Xr4>{QwAnw|B!@WQ{7)4OyONEXV{FpL_Y`VTvScIATIgnQ;H!A z0|SEy5F2GCrliEDR-`7EmLw+Sq-qqUrll68<|U^pz*+immR@o}fhJIw01$%!BM^g3 z0RbQ_0_K1PV!yuYVgX4rZA_dZ&nUe4oBTXRK_Q4bka92(-drc{%Q$g?qCZf5HCR0Z z!&eEQ93NB#hyoddDav5l7=HmMAq60sy2HRb~JH delta 118 zcmez2yTvUrEHih0Xr4>{QwF9ul{4=o3=aDo{rhE$a6rI0k-S886*j}^8;#TK^n~9j uGcYjl0WmUQ1agF+0w5ZO8DhWqo3Vgo88=RzBG1UMSwmqS + +using namespace std; + +template +void f(T &¶m) { + static_assert(std::is_lvalue_reference::value, "T& is lvalue reference"); + cout << "T& is lvalue reference" << endl; +} + +template +class Widget { + typedef T& LvalueRefType; + typedef T&& RvalueRefType; +public: + void judge() { + static_assert(std::is_lvalue_reference::value, "LvalueRefType & is lvalue reference"); + static_assert(std::is_lvalue_reference::value, "RvalueRefType & is lvalue reference"); + cout << "LvalueRefType and RvalueRefType is lvalue reference" << endl; + } + void f(LvalueRefType&& param) { + + } +}; + + +int main() { + int x; + int &&r1 = 10; + int &r2 = x; + f(r1); + f(r2); + + Widget w; + w.judge(); + + + Widget w1, w2; + + auto&& v1 = w1; // v1 is an auto-based universal reference being + // initialized with an lvalue, so v1 becomes an + // lvalue reference referring to w1. + + // 不能编译 +// decltype(w1)&& v2 = w2; // v2 is a decltype-based universal reference, and + // decltype(w1) is Widget, so v2 becomes an rvalue reference. + // w2 is an lvalue, and it’s not legal to initialize an + // rvalue reference with an lvalue, so + // this code does not compile. +} diff --git a/modern_C++_30/reference/don'treturnReference.cpp b/modern_C++_30/reference/don'treturnReference.cpp new file mode 100644 index 0000000..28c3bd9 --- /dev/null +++ b/modern_C++_30/reference/don'treturnReference.cpp @@ -0,0 +1,55 @@ +// +// Created by light on 19-12-15. +// + +#include // std::cout/endl +#include // std::move +using namespace std; +class Obj { +public: + Obj() + { + cout << "Obj()" << endl; + } + Obj(const Obj&) + { + cout << "Obj(const Obj&)" + << endl; + } + Obj(Obj&&) + { + cout << "Obj(Obj&&)" << endl; + } +}; +Obj simple() +{ + Obj obj; +// 简单返回对象;一般有 NRVO + return obj; +} +Obj simple_with_move() +{ + Obj obj; +// move 会禁止 NRVO + return std::move(obj); +} +Obj complicated(int n) +{ + Obj obj1; + Obj obj2; + // 有分支,一般无 NRVO + if (n % 2 == 0) { + return obj1; + } else { + return obj2; + } +} +int main() +{ + cout << "*** 1 ***" << endl; + auto obj1 = simple(); + cout << "*** 2 ***" << endl; + auto obj2 = simple_with_move(); + cout << "*** 3 ***" << endl; + auto obj3 = complicated(42); +} \ No newline at end of file diff --git a/modern_C++_30/reference/forward.cpp b/modern_C++_30/reference/forward.cpp new file mode 100644 index 0000000..41594c4 --- /dev/null +++ b/modern_C++_30/reference/forward.cpp @@ -0,0 +1,45 @@ +// +// Created by light on 19-12-15. +// +#include +#include "../RAII/shape.h" + +void overloaded( int const &arg ) { std::cout << "by lvalue\n"; } +void overloaded( int && arg ) { std::cout << "by rvalue\n"; } + +template< typename t > +/* "t &&" with "t" being template param is special, and adjusts "t" to be + (for example) "int &" or non-ref "int" so std::forward knows what to do. */ +void forwarding( t && arg ) { + std::cout << "via std::forward: "; + overloaded( std::forward< t >( arg ) ); + std::cout << "via std::move: "; + overloaded( std::move( arg ) ); // conceptually this would invalidate arg + std::cout << "by simple passing: "; + overloaded( arg ); +} +void foo(const shape&) +{ + puts("foo(const shape&)"); +} +void foo(shape&&) +{ + puts("foo(shape&&)"); +} +template +void bar(T&& s) +{ + foo(std::forward(s)); +} +int main() { + std::cout << "initial caller passes rvalue:\n"; + forwarding( 5 ); + std::cout << "initial caller passes lvalue:\n"; + int x = 5; + forwarding( x ); + + circle temp; + bar(temp); + bar(circle()); + +} \ No newline at end of file diff --git a/modern_C++_30/reference/lifetime.cpp b/modern_C++_30/reference/lifetime.cpp new file mode 100644 index 0000000..0573197 --- /dev/null +++ b/modern_C++_30/reference/lifetime.cpp @@ -0,0 +1,108 @@ +// +// Created by light on 19-12-15. +// + +#include + +using namespace std; + +class shape { +public: + shape() { cout << "shape" << endl; } + + ~shape() { + cout << "~shape" << endl; + } +}; + +class circle : public shape { +public: + circle() { cout << "circle" << endl; } + + + ~circle() { + cout << "~circle" << endl; + } +}; + +class triangle : public shape { +public: + triangle() { cout << "triangle" << endl; } + + + ~triangle() { + cout << "~triangle" << endl; + } +}; + +class rectangle : public shape { +public: + rectangle() { cout << "rectangle" << endl; } + + ~rectangle() { + cout << "~rectangle" << endl; + } +}; + +class result { +public: + result() { puts("result()"); } + + ~result() { puts("~result()"); } +}; + +result process_shape(const shape &shape1, const shape &shape2) { + puts("process_shape()"); + return result(); +} + + +class Base { +public: + Base() { + cout << "Base()" << endl; + } + + ~Base() { + cout << "~Base()" << endl; + } +}; + +class Derived : public Base { +public: + Derived() { + cout << "Derived()" << endl; + } + + ~Derived() { + cout << "~Derived()" << endl; + } +}; + +string f() { return "abc"; } + +void g() { + const string &s = f(); // still legal? + cout << s << endl; +} + +Derived factory() { + return Derived(); +} + +int main() { + process_shape(circle(), triangle()); + cout << endl; + // 临时对象延迟 +// result &&r = process_shape(circle(), triangle()); + // 临时对象延迟只对rvalue有用,而对xvalue无用! +// result &&r = std::move(process_shape(circle(), triangle())); + +// const Base &b1 = factory(); + + Base *b1 = new Derived; + delete b1; + cout< +#include + +using namespace std; + +// xvalue +int&& f(){ + return 3; +} + +struct As +{ + int i; +}; + +As&& ff(){ + return As(); +} + +int main() { + // lvalue + int x = 0; + cout << "(x).addr = " << &x << endl; + cout << "(x = 1).addr = " << &(x = 1) << endl; + cout << "(++x).addr = " << &++x << endl; + cout << "(cout << ' ').addr=" << &(cout << ' ') << endl; + cout << "(\"hello\").addr=" << &("hello") << endl; + // rvalue + cout<(7); // The expression static_cast(7) belongs to the xvalue category, because it is a cast to an rvalue reference to object type. + std::move(7); // std::move(7) is equivalent to static_cast(7). + + ff().i; // The expression f().i belongs to the xvalue category, because As::i is a non-static data member of non-reference type, and the subexpression f() belongs to the xvlaue category. + + + return 0; +} \ No newline at end of file