C++11再次陪读(169)

最近无聊,读下c++11发现有些东西都忘了。开个页面,来和书同步更新

1、static_assert(条件,提示字符); 这个函数会在编译期间执行。



如上图;

编译器在预编译期间就会报错,无法编译下去。所以里面的条件无法是动态的变量之类的。

2、noexcept和throw(),这个是11和98两个不同的表示方式而已。都一样,如果在函数里面抛的话都会导致程序强制中断。(vs2013无法识别noexcept)

3、final、override、__declspec(novtable).

  • 这个是11的,基类使用。专门放声明虚函数后面(定义放不下);基类对虚函数使用这个修饰符后,子类就无法继承重写那个函数(连同名函数都不允许)
  • 这个是11的,派生类使用。专门放声明虚函数后面;派生类对虚函数使用这个修饰符后,编译器会从基类去找此函数是否是要继承的虚函数(就是和编译器一个君子协定而已),不是就报错。
  • 这个是Microsoft c++。作为接口的基类虽然有纯虚函数声明,但是被继承过后依旧会被分配虚函数表的空间。由于接口基类本来就是可以完全忽略的,所以用这个限定符来把那个表去掉。 但是使用的时候,最好和纯虚函数一起使用(网上说编译器会默认把函数全变成纯虚,但是试了下vs2013,完全不是的。发现它的作用只在去表,没其他的。)

4、using构造特性

struct A {A(int i){} A(int d, double j)};

struct B : A{using A::A};

派生类的构造函数要和基类一样(包括内容),为了方便书写而使用的语法。

5、构造函数委派

个人十分赞扬这种思维:

class Info {
    public:
        Info() : Info(1) {}
        Info(int i):Info(i, 'a') {}
        Info(char e):Info(1, e){}
    private:
        Info(int i, char e):type(i), name(e) {}
        int type;
        char name;
}
//暴漏的接口全委托给private的构造函数了。唉,这个模板好合适哟!!!

6、右值和左值

++
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
class testto
{
public:
testto(int n):m_p(new int(n)) {
int d = 5;
}
~testto() {
delete m_p;
}
testto(testto& d){
int a = 32;
}
testto(testto&& e) :m_p(e.m_p) {
e.m_p = NULL;
}
public:
int * m_p;
};
class sudtest
{
public:
sudtest() :p(new int(3)), h(2){
int da = 45;
}
~sudtest(){
delete p;
}
sudtest& operator = (sudtest& d) {
int a = 2;
}
sudtest(sudtest && e) : p(e.p), h(std::move(e.h)){
e.p = NULL;
}
public:
testto h;
int *p;
};
sudtest gettem() {
sudtest t = sudtest();
return t; }
int _tmain(int argc, _TCHAR* argv[])
{
sudtest a(gettem());
cout << *a.p << endl;
system("pause");
return 0;
}

《C++ 0x 之左值与右值》文中提到 std::forward() 和 std::move()。本文开头对之补充一句:

在操作函数返回值或函数参数时,匿名左值仍然为左值,左值可以具名;匿名右值仍然为右值,右值一旦具名成功,立即转变为左值
  • 先谈move吧,为了节约拷贝函数的空间,要使它走移动构造函数;
  • 1、e由于被命名了所以是左值,必须用move把e.h从左值转化成右值才能调用到testto的移动构造函数。
  • 2、本身传进来的e和t是一样的都是0x71f48a。临时变量就是指源。
  • 3、gettem()函数本身返回的就是临时变量,因为没有移动函数才会去寻复制函数。所以sudtest的移动函数是理所当然的,testto的移动函数是move使之。

在看c++折叠规则:总是优先为左值引用,再右值。int& &&t -> int& t, int&& &&t -> int&& t

fun(int &&m)
fun(int & m)

template<typename T>
fun1(T&& t) {fun(forward<T>(t);)}

int a = 4;
fun1(a)//a此时是左值,调用和fun(t);无区别。
fun1(move(a))//要使用右值了,fun1中对t命名了所以是左值,所以要用forward来转换一下。这就是完美转发。

7、隐式转换

对类进行

operator bool() const {
    return ;
}

//如果对这个隐式转化加个explicit,那么只有构造函数才会传递了。

8、POD模型

1、不定义基本默认函数(构造、析构、移动、复制等)。
2、没有虚函数、
3、父类和成员是POD类型。

9、智能指针

太多了,就说下:

auto_ptr、unique_ptr、shared_ptr、

10、For

for(int &e : a) {}//引用;'/[
for(int e: a){}

11、多线程

c++11是支持多线程编程的。专门使用它的c++函数,这样就可以在多平台使用了。

12、NULL

不同编译器会对NULL不同解释,gcc就是__null,mfc就是0。所以c++11用nullptr来统一。

13、类与默认函数

6个基本函数(移动多了构造和拷贝)、8个默认操作符函数。

14、内存对齐描述符alignas、alignof

struct alignas(32) T {
    int r;
    int g;
    int b;
};
alignof(T);//32;前者是设置对齐字节大小,后者是获取对齐字节大小。

15、Unicode支持

u8"asdf"//utf8字符;
u"asdf"//utf16字符;
U"asdf"//utf32字符;

11说c++支持各种字符的互相转换了,使用codecvt;但是相关资料和代码却一直没看到,只好先放放吧。
// //