c++/c学习笔记 --(6)

来源:互联网 发布:耽美网络剧百度云链接 编辑:程序博客网 时间:2024/06/05 15:36
  1. 关于运算符重载
    1. 不可重载的运算符  ::     .*    .    ?:   , &
    2. 赋值(=)下标([ ]) 调用(( ))成员访问箭头(-〉)运算符(相对的解引用 * 也应该是成员函数)必须是成员函数,复合赋值运算符一般来说也应该是成员。改变对象状态的运算符如自增、自减、解引用等通常也应该是成员,对于这些成员运算符函数应该返回所属类的一个对象。
    3. 具有对称性的运算符可能转换任意一端的运算对象,通常为非成员函数。
    4. 输入和输出运算符必须是非成员函数
    5. 关于自增、自减运算符,前置无参,后置有一个虚参
    6. 关于赋值运算符,可能存在安全风险,其处理方法如前所示,尽可能以swap函数来处理。
    7. 关于关系运算符一般成对出现。
    8. 解引用和箭头运算符均无参。箭头运算符永远不能丢掉成员访问这个基本含义,当重载时,可以改变的是箭头从哪个对象当中获取成员,其他用户什么也不能做。
    9. 函数调用运算符,这个特有名气了,说说优点,可以像函数一样工作。优点是可以有状态。c++11新增的lambda变是以其实现的,但是一个无名的类的函数对象。相应也不能保存状态。但优点是方便。
  2. lambda
    1. 如前所说,其在编译器中的底层实现依旧是一个类函数。
    2. lambda函数的标准形式: [capture](parameters) mutable  ->return-type{statement;}
      1. [capture] 捕捉列表,这在用法上,可以单独捕捉某几个参数,也可以通过[=]以值的方式捕捉所有的外部参数。可以捕捉值,也可能以引用的方式捕捉。另若按值传递,则其在定义函数的那一刻,值已传入函数中,且不会改变的。即若在之后,即合改变了捕捉的外部变量,但前面已定义的lambda函数依旧会使用前值。若需要其跟随外部变量一起变化,需要将其改为引用的传值方式,
        #include <iostream>using namespace std;int main() {int i =4;int j = 5;int k = 8 ;auto f=[i,j](){return i+j;};auto g = [=]()->int{ return i*j*k;};auto l = [&](){return ++i*++j*++k;};auto p=[&i,&j](){i=i+j;j=j-i;};cout << f()<<" "<<g()<<" "<<l()<<endl;cout << i << " "<<j<<" "<<k<<endl;p();cout <<i <<" "<<j<<endl;}


      2. (parameters)参数列表,可省略。
      3. mutable 默认情况下,lambda函数往往是一个const函数,mutable可以取消其常量性,这在值传入时有用。在引用传入时,无此作用。--可省略
        #include <iostream>using namespace std;int main() { int i =4;/*若在此中修改捕捉的i,编译器会报错,在这里要加上mutable修饰符。auto p= [i](){i=9;};*/auto  q = [i]()mutable{i =9;};}

      4. -> return-type ,尾置返回类型,可省略
      5. {statement;}函数主体
    3. c++11标准允许lambda向函数指针转换,前提是函数指针没有任何捕获的变量,且函数指针所示的原型与lambda函数有相同的调用方法。当然,最彻底解决此问题的办法还是标准库中的function<T>类型这样的东西
    4. 最简单的lambda函数,[]{};
  3. 类型转换运算符
    1. 类型转换为隐式执行,故无参,无返回类型。其指类可以转为何种类型
    2. 在c++11中引进了显示类型转换,确保转换按照用户要求。即用户定义类时可以以explicit 声明,再以static_cast<>进行显示转换,
      #include <iostream>using namespace std;struct s{explicit operator double(){ //显示转换声明return .23;}};struct p{operator bool(){return true;}};int main() {s a;cout << static_cast<double>(a)/2; //显示转换//cout << a/2;if(p()){     //隐式转换cout << "operator p is true!";}}
    3. 所以在使用中一定要避免二义性的类型转换
      1. 一是类A可以多种方法转为类B,即B可以通过A的构造函数转为A,也可以通过自己operator A()转为A,这会造成二义性
      2. 避免转换目标是内置算术类型的重载运算符。除了显式地向Bool类型的转换之外,我们应尽量避免定义类型转换函数并尽可能地限制使用。
        1. 不要再定义接受算术类型的重载运算符。
        2. 不要定义转换到多种算术类型的类型转换。
      3. 不要为类同时提供转换目标是算术类型的类型转换,也提供重载的运算符。
0 0
原创粉丝点击