diff --git a/README.md b/README.md index b2fa814..5bbe5a5 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,7 @@ for(decl:col) { - [容器1](./modern_C++_30/container1) - [容器2](./modern_C++_30/container2) - [异常](./modern_C++_30/exception) +- [是不是应该返回对象?](./modern_C++_30/returnObj) ### 4.拓展部分 diff --git a/modern_C++_30/.CMakeLists.txt.un~ b/modern_C++_30/.CMakeLists.txt.un~ index f917ce0..a838cfd 100644 Binary files a/modern_C++_30/.CMakeLists.txt.un~ and b/modern_C++_30/.CMakeLists.txt.un~ differ diff --git a/modern_C++_30/CMakeLists.txt b/modern_C++_30/CMakeLists.txt index 10d8f1b..c92d48c 100644 --- a/modern_C++_30/CMakeLists.txt +++ b/modern_C++_30/CMakeLists.txt @@ -27,3 +27,11 @@ add_executable(relacontainer container2/relacontainer.cpp) add_executable(unorder container2/unorder.cpp) add_executable(array container2/array.cpp) add_executable(exception exception/exception.cpp) + + +add_executable(returnObj returnObj/returnObj1.cpp) +add_executable(returnObj_add returnObj/returnObj2.cpp) +add_executable(returnObj3 returnObj/returnObj3.cpp) +add_executable(returnObj4 returnObj/returnObj4.cpp) +add_executable(returnObj5 returnObj/returnObj5.cpp) +add_executable(rvonrvo returnObj/all.cpp) diff --git a/modern_C++_30/CMakeLists.txt~ b/modern_C++_30/CMakeLists.txt~ index 6791553..10d8f1b 100644 --- a/modern_C++_30/CMakeLists.txt~ +++ b/modern_C++_30/CMakeLists.txt~ @@ -18,3 +18,12 @@ add_executable(forward reference/forward.cpp) add_executable(collapses reference/collapses.cpp) add_executable(lifetime reference/lifetime.cpp) add_executable(dontreturnReference reference/don'treturnReference.cpp) + +add_executable(container container1/container.cpp) +add_executable(cont container2/hash.cpp) +add_executable(vector_l container1/vector_l.cpp) +add_executable(priority_queue container2/priority_queue.cpp) +add_executable(relacontainer container2/relacontainer.cpp) +add_executable(unorder container2/unorder.cpp) +add_executable(array container2/array.cpp) +add_executable(exception exception/exception.cpp) diff --git a/modern_C++_30/returnObj/all.cpp b/modern_C++_30/returnObj/all.cpp new file mode 100644 index 0000000..ff088db --- /dev/null +++ b/modern_C++_30/returnObj/all.cpp @@ -0,0 +1,97 @@ +// +// Created by light on 19-12-23. +// + +#include +#include +#include + +struct Test { + Test() + { + //std::cout << "construct a Test object" << std::endl; + } + + Test(const Test&) + { + std::cout << "copy construct a Test object" << std::endl; + } + + Test& operator=(const Test &t) + { + std::cout << "copy assignment a Test object" << std::endl; + return *this; + } + + Test(Test&& t) + { + std::cout << "move construct a Test object" << std::endl; + } + + Test& operator=(Test &&t) + { + std::cout << "move assignment a Test object" << std::endl; + return *this; + } + + ~Test() + { + //std::cout << "destruct a Test object" << std::endl; + } +}; + +Test getTest() +{ + // anonymous object + return Test(); +} + +Test getTestWithName() +{ + // named return value + Test temp; + return temp; +} +/** + * 1.copy construct本身在RVO和NRVO两种情况下被优化了,如果再加上move反而画蛇添足。 + * 2.加入了move assignment后,默认是调用move assignment而不是copy assignment,可以将move assignment注释后测试。 + * 3.对于RVO和NRVO来说,construction的情况编译器优化得比较好了,加入move语义主要是对于assignment有比较大影响 + */ +int main() +{ + std::cout << "==== common case ====" << std::endl; + Test o1; + std::cout << "---- Test copy construct: " << std::endl; + Test o2(o1); // two ways for copy construct + Test o3 = o1; + std::cout << "---- Test move construct: " << std::endl; + Test o4(std::move(o3)); + std::cout << "---- Test assignment: " << std::endl; + o2 = o1; + std::cout << "---- Test move assignment: " << std::endl; + Test o5; o5 = std::move(o4); + + std::cout << "\n==== test for rvo ===" << std::endl; + std::cout << "---- Test rvo for copy construct: " << std::endl; + Test obj11(getTest()); + Test obj1 = getTest(); + std::cout << "---- Test rvo for move construct: " << std::endl; + Test obj12(std::move(getTest())); + std::cout << "---- Test rvo for assignment: " << std::endl; + Test obj2; obj2 = getTest(); + std::cout << "---- Test rvo move assignment: " << std::endl; + Test obj5; obj5 = std::move(getTest()); + + std::cout << "\n==== test for nrvo ===" << std::endl; + std::cout << "---- Test nrvo for copy construct: " << std::endl; + Test obj33(getTestWithName()); + Test obj3 = getTestWithName(); + std::cout << "---- Test nrvo for move construct: " << std::endl; + Test obj34(std::move(getTestWithName())); + std::cout << "---- Test nrvo for assignment: " << std::endl; + Test obj4; obj4 = getTestWithName(); + std::cout << "---- Test nrvo move assignment: " << std::endl; + Test obj6; obj6 = std::move(getTestWithName()); + + return 0; +} diff --git a/modern_C++_30/returnObj/returnObj1.cpp b/modern_C++_30/returnObj/returnObj1.cpp new file mode 100644 index 0000000..be96c9d --- /dev/null +++ b/modern_C++_30/returnObj/returnObj1.cpp @@ -0,0 +1,49 @@ +// +// Created by light on 19-12-22. +// + + +// rvo example + +#include + +using namespace std; + +// Can copy and move +class A { +public: + A() { cout << "Create A\n"; } + + ~A() { cout << "Destroy A\n"; } + + A(const A &) { cout << "Copy A\n"; } + + A(A &&) { cout << "Move A\n"; } + + + A& operator=(const A&a) + { + std::cout << "copy assignment" << std::endl; + return *this; + } + + A& operator=(A &&a) { + cout << "move assignment\n"; + return *this; + } + +}; + +// 编译器可以优化 返回值移动出去 +A getA_unnamed() { + return A(); +} + +int main() { +// cout<<"构造"< + +using namespace std; + +// Can copy and move +class A { +public: + A() { cout << "Create A\n"; } + + ~A() { cout << "Destroy A\n"; } + + A(const A &) { cout << "Copy A\n"; } + + A(A &&) { cout << "Move A\n"; } + + + A& operator=(const A&a) + { + std::cout << "copy assignment" << std::endl; + return *this; + } + + A& operator=(A &&a) { + cout << "move assignment\n"; + return *this; + } +}; + +// 编译器可以优化 返回值移动出去 +A getA_named() { + A a; + return a; +} + +int main() { +// cout<<"拷贝"< + +using namespace std; + +// Can copy and move +class A { +public: + A() { cout << "Create A\n"; } + + ~A() { cout << "Destroy A\n"; } + + A(const A &) { cout << "Copy A\n"; } + + A(A &&) { cout << "Move A\n"; } + + A& operator=(const A&a) + { + std::cout << "copy assignment" << std::endl; + return *this; + } + + A& operator=(A &&a) { + cout << "move assignment\n"; + return *this; + } +}; +// 编译器无法优化 +A getA_duang() { + A a1; + A a2; + if (rand() > 42) { + return a1; + } + else { + return a2; + } +} + +int main() { +// cout<<"拷贝"< + +using namespace std; + +// Can copy and move +class A { +public: + A() { cout << "Create A\n"; } + + ~A() { cout << "Destroy A\n"; } + + A(const A &) { cout << "Copy A\n"; } + + A(A&&)= delete; +}; + +A getA_duang() { + A a1; + A a2; + if (rand() > 42) { + return a1; + } + else { + return a2; + } +} + +int main() { + auto a = getA_duang(); +} \ No newline at end of file diff --git a/modern_C++_30/returnObj/returnObj5.cpp b/modern_C++_30/returnObj/returnObj5.cpp new file mode 100644 index 0000000..96691f4 --- /dev/null +++ b/modern_C++_30/returnObj/returnObj5.cpp @@ -0,0 +1,31 @@ +// +// Created by light on 19-12-22. +// + + +#include + +using namespace std; + +// Can copy and move +class A { +public: + A() { cout << "Create A\n"; } + + ~A() { cout << "Destroy A\n"; } + +// A(const A &) { cout << "Copy A\n"; } +// +// A(A &&) { cout << "Move A\n"; } + + A(const A&&)= delete; + A(A&&)= delete; +}; + +A getA_unnamed() { + return A(); +} + +int main() { + auto a = getA_unnamed(); +} \ No newline at end of file