C++11常见语法总结

19 篇文章 0 订阅
7 篇文章 0 订阅

Override 关键字:

明确的表示一个函数是对基类中一个虚函数的重载。

class G

{

public:

 virtualvoid func(int);

};

class H: G

{

public:

 virtualvoid func(double) override; //compilation error

};

当处理到H::func()声明时,编译器会 在一个基类查找与之匹配的虚函数。

final函数和类:

C++11有两个用途,第一阻止从类继承,第二阻止一个虚函数的重载。

无子类类型:

classTaskManager

{

/*..*/

} final;

classPrioritizedTaskManager: publicTaskManager

{

};  //compilationerror: base classTaskManagerisfinal

禁止虚函数被进一步重载:

classA

{

pulic:

 virtual void func() const;

};

class  B: A

{

pulic:

  void func() constoverridefinal; //OK

};

classC:B

{

pulic:

 void func()const; //error, B::func is final

};

C++11之右值引用:

左值是指表达式结束后依然存在的持久对象,右值是指表达式结束时就不再存在的临时对象,一个区分左值右值的便捷方法是:看能不能对表达式取地址,如果能,就是左值,否则为右值。

 

右值一般指的是表达式中的临时变量,在C++中临时

 

变量在表达式结束后就被销毁了,之后程序就无法再引用这个变量了,C++11提供了一个方法,让我们可以引用这个临时变量,这个方法就是所谓右值引用。

那么右值引用有什么用呢?避免内存copy!因此对于赋值操作意味着内存拷贝而不是简单的赋值指针。而右值引用的一个作用就是我们可以通过重新利用临时变量(右值)来避免无意义的内存copy。

 

右值引用的符号:“&&”

int a = 0;

a是一个左值,左值是一个变量,可以被引用和多次使用。0是一个右值,不可以被引用。左值一般是非临时变量,可以被多次使用。右值只在当前表达式有效。

classMyClassB

{

public:

    void init(int & intval)

    { cout<<"use & print"<<endl;};

    void init(int &&intval)

    { cout<<"use && print"<<endl;}

};

intmain(void)

{

    int ae = 10;

   MyClassB().init(10);

   MyClassB().init(ae);

    return0;

}

右值引用是用来支持转移语义,转移语义可以将资源从一个对象转移到另一个对象,这样可以减少不必要的临时对象的创建,拷贝及销毁,大幅度提高C++应用程序的性能。

浅拷贝与move语义的区别在于,浅拷贝是共享资源,而move是独占资源,浅拷贝因共享资源从而可能引发重复析构的问题,而move是独占则不会

标准库函数 std::move

以非常简单的方式将左值引用转换为右值引用。

IBM Developer 正在整合其语言站点组合。 – IBM Developer

我们先定义转移构造函数。

  MyString(MyString&& str) {

    std::cout << "Move Constructoris called! source: " << str._data << std::endl;

    _len = str._len;

    _data = str._data;

    str._len = 0;

    str._data = NULL;

 }

和拷贝构造函数类似,有几点需要注意:

1. 参数(右值)的符号必须是右值引用符号,即“&&”

2. 参数(右值)不可以是常量,因为我们需要修改右值。

3. 参数(右值)的资源链接和标记必须修改。否则,右值的析构函数就会释放资源。转移到新对象的资源也就无效了。

 

 

示例程序 :

 void ProcessValue(int& i) { 
  std::cout << "LValue processed: " << i << std::endl; 
 } 
 
 void ProcessValue(int&& i) { 
  std::cout << "RValue processed: " << i << std::endl; 
 } 
 
 int main() { 
  int a = 0; 
  ProcessValue(a); 
  ProcessValue(std::move(a)); 
 }

运行结果 :

 LValue processed: 0 
 RValue processed: 0

 

精确传递(Perfect Forwarding)

Lambda表达式解析:

 

Lambda表达式是右值引用。

方便的构造匿名函数,如果代码存在大量小函数,而这些函数一般只被调用一次,不妨将他们重构成lambda表达式。

[ capture ] ( params ) mutable exception attribute -> ret { body }

(1)

 

[ capture ] ( params ) -> ret { body }

(2)

 

[ capture ] ( params ) { body }

(3)

 

[ capture ] { body }

(4)

 

其中

·        (1) 是完整的 lambda表达式形式,

·        (2) const 类型的 lambda表达式,该类型的表达式不能改捕获("capture")列表中的值。

·        (3)省略了返回值类型的 lambda表达式,但是该 lambda 表达式的返回类型可以按照下列规则推演出来:

·        如果 lambda代码块中包含了 return 语句,则该 lambda 表达式的返回类型由 return语句的返回类型确定。

·        如果没有 return语句,则类似 void f(...) 函数。

·        省略了参数列表,类似于无参函数 f()

mutable 修饰符说明 lambda 表达式体内的代码可以修改被捕获的变量,并且可以访问被捕获对象的 non-const 方法。

exception 说明 lambda 表达式是否抛出异常(noexcept),以及抛出何种异常,类似于void f() throw(X,Y)

attribute 用来声明属性。

另外,capture 指定了在可见域范围内 lambda 表达式的代码内可见得外部变量的列表,具体解释如下:

·        [a,&b] a变量以值的方式呗捕获,b以引用的方式被捕获。

·        [this] 以值的方式捕获 this 指针。

·        [&] 以引用的方式捕获所有的外部自动变量。

·        [=] 以值的方式捕获所有的外部自动变量。

·        [] 不捕获外部的任何变量。

此外,params 指定 lambda表达式的参数。

————————————————————————————

CharString之间的转换

C++char类型可以自动转换成string类型,即你可以用char类型字符串直接给string类型变量赋值。但反过来是不行的,string类型不能隐式的将string类型转换成char类型,想要转换,必须显式调用c_str()函数。给你举个例子:
string s1;
const char *pc = "a character array";
s1 = pc; // ok

char *str = s1; // 
编译时刻类型错误

const char *str = s1.c_str(); // ok

————————————————————

explicit构造函数的作

解析

explicit构造函数是用来防止隐式转换的。请看下面的代码


 

class Test1

{

public:

    Test1(int n)

    {

        num=n;

    }//普通构造函数

private:

    int num;

};

class Test2

{

public:

    explicit Test2(int n)

    {

        num=n;

    }//explicit(显式)构造函数

private:

    int num;

};

int main()

{

    Test1 t1=12;//隐式调用其构造函数,成功

    Test2 t2=12;//编译错误,不能隐式调用其构造函数

    Test2 t2(12);//显式调用成功

    return 0;

}

普通构造函数能够被隐式调用。而explicit构造函数只能被显式调用Test1构造函数带一个int型的参数,代码23行会隐式转换成调用Test1的这个构造函数。而Test2的构造函数被声明为explicit(显式),这表示不能通过隐式转换来调用这个构造函数,因此代码24行会出现编译错误

————————————————————————

std::ifstream的使用方法和作用

ifstream 已有的文件

————————————————————————

Decltype

https://www.devbean.net/2012/05/cpp11-decltype/

decltype 类型说明符生成指定表达式的类型。在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。

int  var;

const  int  &&fx();

struct  A { doublex; }

const  A* a = new A();

 

 

语句

类型

注释

decltype(fx());

const int &&

对左值引用的const int

decltype(var);

int

变量 var 的类型

decltype(a->x);

double

成员访问的类型

decltype((a->x));

const double&

内部括号导致语句作为表达式而不是成员访问计算。由于a声明为 const指针,因此类型是对const double的引用。

 

——————————————————

 Deletedefault

 

http://blog.csdn.net/u012333003/article/details/25299939

1.   class LeafFromTree{  

2.   public:  

3.     LeafFromTree() = default;  

4.     ~LeafFromTree() = default;  

5.     

6.     LeafFromTree( const LeafFromTree& ) = delete;  // mark copy ctor or copy assignment operator as deleted functions  

7.     LeafFromTree & operator=( const LeafFromTree &) = delete;   

8.   };  

 

9.     在函数重载中,可用 delete 来滤掉一些函数的形参类型,如下:

10.bool isLucky(int number);        // original function
11.bool isLucky(char) = delete;     // reject chars
12.bool isLucky(bool) = delete;     // reject bools
13.bool isLucky(double) = delete;   // reject doubles and floats

14.    这样在调用 isLucky 函数时,如果参数类型不对,则会出现错误提示

15.if (isLucky('a')) …     // error !    call to deleted function
16.if (isLucky(true)) …    // error !
17.if (isLucky(3.5)) …     // error !

 

 

 C++11 中,可在想要禁止使用的函数声明后加= delete,而需要保留的加"= default" 或者不采取操

 

 

 

Constexpr

 

map/unordered_map原理和使用整理

运行效率方面:unordered_map最高,而map效率较低但提供了稳定效率和有序的序列。

占用内存方面:map内存占用略低,unordered_map内存占用略高,而且是线性成比例的。

需要无序容器,快速查找删除,不担心略高的内存时用unordered_map;有序容器稳定查找删除效率,内存很在意时候用map。

 

 

Tuple(元组)

tuple是一个固定大小的不同类型值的集合,是泛化的std::pair。和c#中的tuple类似,但是比c#中的tuple强大得多。我们也可以把他当做一个通用的结构体来用,不需要创建结构体又获取结构体的特征,在某些情况下可以取代结构体使程序更简洁,直观。

创建右值的引用元组方法:forward_as_tuple。

    std::map<int, std::string> m;
 
    m.emplace(std::piecewise_construct,
              std::forward_as_tuple(10),
              std::forward_as_tuple(20, 'a'));
    std::cout << "m[10] = " << m[10] << '\n';

output : m[10] = aaaaaaaaaaaaaaaaaaaa

它实际上创建了一个类似于std::tuple<int&&,std::string&&>类型的tuple。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值