update
This commit is contained in:
parent
e1638bc224
commit
b7dc636c14
@ -129,11 +129,16 @@ for(decl:col) {
|
|||||||
- [堆](./modern_++_30/RAII/heap.cpp)
|
- [堆](./modern_++_30/RAII/heap.cpp)
|
||||||
- [栈](./modern_C++_30/RAII/stack.cpp)
|
- [栈](./modern_C++_30/RAII/stack.cpp)
|
||||||
- [RAII](./modern_C++_30/RAII/RAII.cpp)
|
- [RAII](./modern_C++_30/RAII/RAII.cpp)
|
||||||
|
|
||||||
- [自己动手,实现C++的智能指针](./modern_C++_30/smart_ptr)
|
- [自己动手,实现C++的智能指针](./modern_C++_30/smart_ptr)
|
||||||
- [auto_ptr、scope_ptr](./modern_C++_30/smart_ptr/auto_scope.cpp)
|
- [auto_ptr、scope_ptr](./modern_C++_30/smart_ptr/auto_scope.cpp)
|
||||||
- [unique_ptr](./modern_C++_30/smart_ptr/unique_ptr.cpp)
|
- [unique_ptr](./modern_C++_30/smart_ptr/unique_ptr.cpp)
|
||||||
- [shared_ptr](./modern_C++_30/smart_ptr/shared_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.拓展部分
|
### 4.拓展部分
|
||||||
|
|
||||||
|
Binary file not shown.
@ -12,3 +12,9 @@ add_executable(auto_scope smart_ptr/auto_scope.cpp)
|
|||||||
add_executable(unique_ptr smart_ptr/unique_ptr.cpp)
|
add_executable(unique_ptr smart_ptr/unique_ptr.cpp)
|
||||||
add_executable(unique_ptr_U smart_ptr/unique_ptr_U.cpp)
|
add_executable(unique_ptr_U smart_ptr/unique_ptr_U.cpp)
|
||||||
add_executable(shared_ptr smart_ptr/shared_ptr.cpp)
|
add_executable(shared_ptr smart_ptr/shared_ptr.cpp)
|
||||||
|
|
||||||
|
add_executable(reference reference/reference.cpp)
|
||||||
|
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)
|
||||||
|
14
modern_C++_30/CMakeLists.txt~
Normal file
14
modern_C++_30/CMakeLists.txt~
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
project(Morden_C++)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
|
add_executable(heap RAII/heap.cpp)
|
||||||
|
add_executable(stack RAII/stack.cpp)
|
||||||
|
add_executable(RAII RAII/RAII.cpp)
|
||||||
|
add_executable(RAII_fstram RAII/RAII_fstram.cpp)
|
||||||
|
|
||||||
|
add_executable(auto_scope smart_ptr/auto_scope.cpp)
|
||||||
|
add_executable(unique_ptr smart_ptr/unique_ptr.cpp)
|
||||||
|
add_executable(unique_ptr_U smart_ptr/unique_ptr_U.cpp)
|
||||||
|
add_executable(shared_ptr smart_ptr/shared_ptr.cpp)
|
53
modern_C++_30/reference/collapses.cpp
Normal file
53
modern_C++_30/reference/collapses.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// Created by light on 19-12-15.
|
||||||
|
//
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void f(T &¶m) {
|
||||||
|
static_assert(std::is_lvalue_reference<T>::value, "T& is lvalue reference");
|
||||||
|
cout << "T& is lvalue reference" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class Widget {
|
||||||
|
typedef T& LvalueRefType;
|
||||||
|
typedef T&& RvalueRefType;
|
||||||
|
public:
|
||||||
|
void judge() {
|
||||||
|
static_assert(std::is_lvalue_reference<LvalueRefType>::value, "LvalueRefType & is lvalue reference");
|
||||||
|
static_assert(std::is_lvalue_reference<RvalueRefType>::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<int &> w;
|
||||||
|
w.judge();
|
||||||
|
|
||||||
|
|
||||||
|
Widget<int> 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.
|
||||||
|
}
|
55
modern_C++_30/reference/don'treturnReference.cpp
Normal file
55
modern_C++_30/reference/don'treturnReference.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// Created by light on 19-12-15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream> // std::cout/endl
|
||||||
|
#include <utility> // 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);
|
||||||
|
}
|
45
modern_C++_30/reference/forward.cpp
Normal file
45
modern_C++_30/reference/forward.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// Created by light on 19-12-15.
|
||||||
|
//
|
||||||
|
#include <iostream>
|
||||||
|
#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 <typename T>
|
||||||
|
void bar(T&& s)
|
||||||
|
{
|
||||||
|
foo(std::forward<T>(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());
|
||||||
|
|
||||||
|
}
|
108
modern_C++_30/reference/lifetime.cpp
Normal file
108
modern_C++_30/reference/lifetime.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
//
|
||||||
|
// Created by light on 19-12-15.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
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<<endl;
|
||||||
|
Derived d;
|
||||||
|
Base &b2 =d;
|
||||||
|
}
|
43
modern_C++_30/reference/reference.cpp
Normal file
43
modern_C++_30/reference/reference.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// Created by light on 19-12-14.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
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<<true<<endl;
|
||||||
|
// xvalue
|
||||||
|
f(); // The expression f() belongs to the xvalue category, because f() return type is an rvalue reference to object type.
|
||||||
|
static_cast<int&&>(7); // The expression static_cast<int&&>(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<int&&>(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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user