1. 程式人生 > >程式設計與演算法(三)第十週 c++新特性和c++高階主題 (1)

程式設計與演算法(三)第十週 c++新特性和c++高階主題 (1)

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

#include <iostream>
using namespace std;
class A{};
A operator+(int n, const A& a)
{
    return a;
}
template<class T1, class T2>
auto add(T1 x, T2 y)-> decltype(x+y){
    return x+y;
};
int main()
{
    auto d = add(100, 1.5);// d是double d = 101.5
    auto k = add(100, A());// d是A型別
cout<<d; }

在這裡插入圖片描述
在這裡插入圖片描述

#include <memory>
#include <iostream>
using namespace std;
struct A{
    int n;
    A(int v=0):n(v){}
    ~A(){cout<<n<<" destructor"<<endl;}
};
int main()
{
    shared_ptr<A> sp1(new A(2));
    shared_ptr<A> sp2(sp1);
    // 上面是sp1和sp2共同託管A(2)
cout<<"1)"<<sp1->n<<","<<sp2->n<<endl; shared_ptr<A> sp3; A*p = sp1.get();//p指向A(2) cout<<"2)"<<p->n<<endl; sp3=sp1;//sp3也託管了A(2) cout<<"3)"<<(*sp3).n<<endl; sp1.reset(); if(!sp1) cout<<
"4) sp1 is null"<<endl; A *q=new A(3); sp1.reset(q);//sp1託管q cout<<"5)"<<sp1->n<<endl; shared_ptr<A>sp4(sp1); shared_ptr<A>sp5; // sp5.reset(q)不妥,會報錯 sp1.reset(); cout<<"before end main"<<endl; sp4.reset(); cout<<"end main"<<endl; return 0; }
1)2,2
2)2
3)2
4) sp1 is null
5)3
before end main
3 destructor
end main
2 destructor

在這裡插入圖片描述
在這裡插入圖片描述

// 基於範圍的for迴圈
#include <iostream>
#include <vector>
using namespace std;
struct A{
    int n;
    A(int i):n(i){}
};
int main()
{
    int ary[]={1,2,3,4,5};
    for(int &e:ary)
        e*=10;
    for(int e:ary)
        cout<<e<<",";
    cout<<endl;
    vector<A> st(ary, ary+5);
    for(auto &it:st)
        it.n*=10;
    for(A it:st)
        cout<<it.n<<",";
    return 0;
}

在這裡插入圖片描述

#include <iostream>
#include <string>
#include <cstring>
using namespace std;
class String{
public:
    char *str;
    String():str(new char[1]){str[0]=0;}
    String(const char *s){
        cout<<"constructor called"<<endl;
        str = new char[strlen(s)+1];
        strcpy(str, s);
    }
    // 複製建構函式
    String(const String &s){
        cout<<"copy constructor called"<<endl;
        str = new char[strlen(s.str)+1];
        strcpy(str, s.str);
    }
    String & operator=(const String&s){
        cout<<"copy operator = called"<<endl;
        if(str!=s.str){
            delete[] str;
            str=new char[strlen(s.str)+1];
            strcpy(str, s.str);
        }
        return *this;
    }
    // 移動建構函式
    String(String &&s):str(s.str){
        // 直接指向引數s.str指向的地方,然後把原來的改變就可以了
        // 沒有進行深拷貝
        cout<<"move constructor called"<<endl;
        s.str = new char[1];
        s.str[0] = 0;
    }
    String & operator=(String &&s){
        cout<<"move operator= called"<<endl;
        if(str!=s.str){
            delete[] str;
            str = s.str;
            s.str = new char[1];
            s.str[0] = 0;
        }
        return *this;
    }
    ~String(){delete[] str;}
};
template <class T>
void MoveSwap(T& a, T& b)
{

    T tmp(move(a));// std::move(a)為右值,這裡呼叫move constructor
    a = move(b);// move(b) 為右值,因此這裡會呼叫move assigment
    b = move(tmp);// move(tmp) 為右值,因此這裡會呼叫move assigment
}
int main()
{
    //這裡注意a,b的值會被修改,但是會避免深拷貝
    // String &r = String("string");//error,物件是一個右值,這裡寫成了左值
    String s;
    s = String("ok");// String("ok")是右值,呼叫引數為右值的賦值過載運算子
    cout<<"****"<<endl;
    String &&r = String("this");
    cout<<r.str<<endl;
    String a("hello"), b("world");
    MoveSwap(a, b);
    cout<<a.str<<endl;
    return 0;
}

constructor called
move operator= called
****
constructor called
this
constructor called
constructor called
move constructor called
move operator= called
move operator= called
world