cpp 11&14 default&delete 以及template

  • default&delete
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Zoo{
    public:
    //big five 可以运用到default,其它函数上会报错
    Zoo(int i1,int i2):d1(i1),d2(i2){}//构造函数
    Zoo(const Zoo&)=delete;//拷贝构造函数,不要这个函数,不可以使用
    Zoo(Zoo&&)=default;//右值引用,使用编译器默认的版本
    Zoo& operator=(const Zoo&)=default;//拷贝赋值
    Zoo& operator=(const Zoo&&)=delete;//移动赋值
    virtual ~Zoo(){};
    private:
    int d1,d2;
    };
  • alias Template
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    template <typename T>
    using Vec=std::vector<T,MyAlloc<T>>;
    Vec<int> coll;

    // 使用宏定义
    #define Vec<T> template<typename T> std::vector<T,MyAlloc<T>>;
    Vec<int> coll;
    //template<typename int> std::vector<int,MyAlloc<int>> 是这样的效果

    //使用typedef,因为typedef 不接收参数,只能使用如下所示
    typedef std::vector<int,MyAlloc<int>> Vec;
  • template template parameter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template<typename T,template<class> class Container>
//template<typename T,template<typename> class Container>
class XCIs
{
private:
Container<T> c;
public:
XCIs(){
for(long i=0;i<SIZE;i++){
c.insert(c.end(),T());
}
output_static_data(T());
Container<T> c1(c);
Container<T> c2(std::move(c));
c1.swap(c2);
}
}

default&delete

何时需要写出big 5 函数,类中含有指针时需要写出

code

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Foo{
public:
Foo(int i):_i(i){}
Foo()=default;//默认构造
Foo(const Foo&x):_i(x.i){}
// Foo(const Foo&)=default;//存在重名函数
// Foo(const Foo&)=delete;//与函数定义冲突
Foo& operator=(const Foo&x){_i=x.i;return *this;}
//Foo& operator=(const Foo& x)=default;//赋值构造函数
//Foo& operator=(const Foo& x)=delete;
// void func1()=default;//[Error] 'void Foo::func1()' 没有默认的函数实现
void func2()=delete
// ~Foo()=delete;//析构函数不能被delete
~Foo()=default;
private:
int _i;
}

Foo f1(5)//构造
Foo f2;//如果没有默认无参数构造会报错
Foo f3(f1)// 如果拷贝构造呗delete会报错
f3=f2 //如果赋值构造被delete 会被报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

struct NoCopy{
NoCopy()=default;
NoCopy(const NoCopy&)=delete; //禁止拷贝构造
NoCopy &operator=(const NoCopy&)=delete //禁止赋值构造
}

class PrivateCopy{
private:
PrivateCopy(const PrivateCopy&);
PrivateCopy &operator=(const PrivateCopy&);
//私有函数可被自己以及友元使用
}

namespace boost{
namespace noncopyable_ {//
class noncopyable{
protected:
noncopyable(){}
~noncopyable(){}
private:
noncopyable(const noncopyable&);
const noncopyable& operator=(const noncopuable&);
};
}

//用于集成,以实现不允许拷贝的操作
}

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Empty{};
//当函数被调用后,编译器会生成对应的默认函数,都是内联函数
{
class Empty{
public:

//=======================//
//*********************//
// Empty e1; 使用默认构造,用于存放背后的代码,例如子类调用父类的构造函数
Empty(){...}
~Empty(){}
//*********************//

//=======================//
//*********************//
// Empty e2(e1); 使用拷贝构造
Empty(const Empty& rhs){...}
//*********************//

//=======================//
//*********************//
// Empty e2(e1); 使用拷贝构造
Empty(const Empty& rhs){...}
//*********************//

//=======================//
//*********************//
// e2 = e1 生成赋值构造
Empty& operator = (const Empty& rhs){}
//*********************//

}


}

Alias(别名)

code

1
2
3
4
5
6
7
8
9
10
11
12

template <typename T>
using Vec=std::vector<T,MyAlloc<T>>;
Vec<int> coll;

// 使用宏定义
#define Vec<T> template<typename T> std::vector<T,MyAlloc<T>>;
Vec<int> coll;
//template<typename int> std::vector<int,MyAlloc<int>> 是这样的效果

//使用typedef,因为typedef 不接收参数,只能使用如下所示
typedef std::vector<int,MyAlloc<int>> Vec;

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

// 函数目的,测试当前类型,是否都禁止了移动构造函数
// 实现这样的效果需要使用 模板模板参数
void test_moveable(Container cntr,T elem){
Container<T> c;
for(long i=0;i<SIZE;++i)
c.insert(c.end(),T());
output_static_data(T());
Container<T> c1(c);
Container<T> c2(std::move(c));
c1.swap(c2);
}

test_moveable(list,MyString);
test_moveable(list,MyStrNoMove);

// 改进
//Error expected nested-name-specifier before is Container
template<typename Container,typename T>
void test_moveable(Container cntr,T elem){
typename Container<T> c;
for(long i=0;i<SIZE;++i)
c.insert(c.end(),T());
output_static_data(T());
Container<T> c1(c);
Container<T> c2(std::move(c));
c1.swap(c2);
}

test_moveable(list(),MyString());
test_moveable(list(),MyStrNoMove());


//最终版本

template<typename Container>
void test_moveable(Container cntr){

//取出容器的内部的类型
typedef typename iterator_traits<typename Container::iterator>::value_type Valtype();
typename Container<T> c;
for(long i=0;i<SIZE;++i)
c.insert(c.end(),Valtype());
output_static_data(*(c.begin()));// 查看哪些静态数据被频繁的调用
Container<T> c1(c);
Container<T> c2(std::move(c));
c1.swap(c2);
}

test_moveable(list<MyString>());
test_moveable(list<MyStrNoMove>());

//使用RB-tree 时,元素需提供operator<
//使用hashTable 时,元素需提供 operator <,hash function>
//使用multi-容器是,元素还需提供operator ==

模板模板参数

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
template<class> class
// template<class> class 表示该位置是一个模板类
// template<typename> 效果相同
template<typename T,template<class> class Container>
//template<typename T,template<typename> class Container>
class XCIs
{
private:
Container<T> c;
public:
XCIs(){
for(long i=0;i<SIZE;i++){
c.insert(c.end(),T());
}
output_static_data(T());
Container<T> c1(c);
Container<T> c2(std::move(c));
c1.swap(c2);
}
}


XCIS<Mystring,vector>c1; // 使用的时候报错,因为模板需要两个参数,而使用时只有一个模板册数

template<typename _Tp,typename _Alloc = std::allocator<_Tp>>//模板函数的默认值,第二个参数以第一个参数为参数
class vector :protected _Vector_vase<_tp,_Alloc>{

}

// 最终实现
// 不可以在函数体内声明
template<typename T>
using Vec=vector<T,allocator<T>>;
XCIS<Mystring,Vec>c1;