C++深度解析教程笔记11ok-智能指针,逻辑&逗号&自增操作符,类型转换函数

本文学习自狄泰软件学院 唐佐林老师的 C++深度解析教程,图片全部来源于课程PPT,仅用于个人学习记录

第37课 - 智能指针分析

在这里插入图片描述

实验-内存未释放并优化

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int i;
public:
    Test(int i)//带参数的构造函数
    {
        this->i = i;
		cout<<"Test();"<<endl;
    }
    int value()
    {
        return i;
    }
    ~Test()//析构函数
    {
		cout<<"~Test();"<<endl;
    }
};
//优化,定义一个指针类,成员变量类型为Test*
class pointer
{
	 Test * mp;
public:
	pointer(Test* p=NULL)//构造函数默认值为NULL
	{
		mp=p;
	
	}
	Test * operator ->()
	{
	return mp;
	}
	Test  operator *()
	{
	return *mp;
	}
	~pointer()
	{
	delete mp;
	
	}
	


};

int main()
{
    for(int i=0; i<5; i++)
    {
        //Test* p = new Test(i);
//优化
       pointer p = new Test(i);
        
        cout << p->value() << endl;
        
    
    }
    
    return 0;
}


在这里插入图片描述
在这里插入图片描述

实验-指针作为类

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int i;
public:
    Test(int i)
    {
        cout << "Test(int i)" << endl;
        this->i = i;
    }
    int value()
    {
        return i;
    }
    ~Test()
    {
        cout << "~Test()" << endl;
    }
};

class Pointer
{
    Test* mp;
public:
    Pointer(Test* p = NULL)
    {
        mp = p;
    }
    Pointer(const Pointer& obj)
    {
        mp = obj.mp;
        const_cast<Pointer&>(obj).mp = NULL;
    }
    Pointer& operator = (const Pointer& obj)
    {
        if( this != &obj )
        {
            delete mp;
            mp = obj.mp;
            const_cast<Pointer&>(obj).mp = NULL;
        }
        
        return *this;
    }
    Test* operator -> ()
    {
        return mp;
    }
    Test& operator * ()
    {
        return *mp;
    }
    bool isNull()
    {
        return (mp == NULL);
    }
    ~Pointer()
    {
        delete mp;
    }
};

int main()
{
    Pointer p1 = new Test(0);
    
    cout << p1->value() << endl;
    
    Pointer p2 = p1;
    
    cout << p1.isNull() << endl;
    
    cout << p2->value() << endl;
    
    return 0;
}
/*
Test(int i)
0
1
0
~Test()

*/

智能指针的使用军规
只能用来指向堆空间中的对象或者变量

小结

指针特征操作符(->和*)可以被重载重载
指针特征符能够使用对象代替指针
智能指针只能用于指向堆空间中的内存
智能指针的意义在于最大程度的避免内存问题

第38课 - 逻辑操作符的陷阱

逻辑运算符的原生语义
一操作数只有两种值(true和false)
一逻辑表达式不用完全计算就能确定最终值一最终结果只能是true或者false

实验-逻辑与或

#include <iostream>
#include <string>

using namespace std;

int func(int i)
{
    cout << "int func(int i) : i = " << i << endl;
    
    return i;
}

int main()
{
    if( func(0) && func(1) )
    {
        cout << "Result is true!" << endl;
    }
    else
    {
        cout << "Result is false!" << endl;
    }
    
    cout << endl;
    
    if( func(0) || func(1) )
    {
        cout << "Result is true!" << endl;
    }
    else
    {
        cout << "Result is false!" << endl;
    }
    
    return 0;
}
/*
int func(int i) : i = 0
Result is false!

int func(int i) : i = 0
int func(int i) : i = 1
Result is true!
*/

逻辑操作符可以重载吗?重载逻辑操作符有什么意义?

实验-重载与或

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int mValue;
public:
    Test(int v)
    {
        mValue = v;
    }
    int value() const
    {
        return mValue;
    }
};

bool operator && (const Test& l, const Test& r)
{
    return l.value() && r.value();
}

bool operator || (const Test& l, const Test& r)
{
    return l.value() || r.value();
}

Test func(Test i)
{
    cout << "Test func(Test i) : i.value() = " << i.value() << endl;
    
    return i;
}

int main()
{
    Test t0(0);
    Test t1(1);
    
    if( operator && (func(t0) , func(t1)))
    {
        cout << "Result is true!" << endl;
    }
    else
    {
        cout << "Result is false!" << endl;
    }
    
    cout << endl;

     if( func(t0) && func(t1) )
    {
        cout << "Result is true!" << endl;
    }
    else
    {
        cout << "Result is false!" << endl;
    }
    
    cout << endl;

    if( operator ||(func(t0), func(t1)  ))
    {
        cout << "Result is true!" << endl;
    }
    else
    {
        cout << "Result is false!" << endl;
    }
    
    cout << endl;
    
    if( func(1) || func(0) )
    {
        cout << "Result is true!" << endl;
    }
    else
    {
        cout << "Result is false!" << endl;
    }
    
    return 0;
}
/*
Test func(Test i) : i.value() = 1
Test func(Test i) : i.value() = 0
Result is false!

Test func(Test i) : i.value() = 1
Test func(Test i) : i.value() = 0
Result is false!

Test func(Test i) : i.value() = 1
Test func(Test i) : i.value() = 0
Result is true!

Test func(Test i) : i.value() = 0
Test func(Test i) : i.value() = 1
Result is true!

*/

■一些有用的建议
一实际工程开发中避免重载逻辑操作符
一通过重载比较操作符代替逻辑操作符重载
一直接使用成员函数代替逻辑操作符重载
一使用全局函数对逻辑操作符进行重载

逻辑操作符重载后无法完全实现原生的语义
问题的本质分析
1.C++通过函数调用扩展操作符的功能
2.进入函数体前必须完成所有参数的计算
3.函数参数的计算次序是不定的
4.短路法则完全失效

小结

C++从语法上支持逻辑操作符重载
重载后的逻辑操作符不满足短路法则
工程开发中不要重载逻辑操作符
通过重载比较操作符替换逻辑操作符重载
通过专用成员函数替换逻辑操作符重载

第39课 - 逗号操作符的分析

逗号操符(,)构成逗号表达式
一逗号表达式用于将多个子表达式接为一人表达式一逗号表达式的值为最后一个子表达式的值
一逗号表达式中的前N-1人子表达式可以没有返回值
一逗号表达式按照从左向右的顺序计算每个子表达式的值 expl, exp2, exp3, … , expN

实验-逗号表达式

#include <iostream>
#include <string>

using namespace std;

void func(int i)
{
    cout << "func() : i = " << i << endl;
}

int main()
{   
    int a[3][3] = {
        (0, 1, 2),
        (3, 4, 5),
        (6, 7, 8)
    };
  /*int a[3][3] = {
        {0, 1, 2},
        {3, 4, 5},
        {6, 7, 8}
    };*/
    
    int i = 0;
    int j = 0;
    
    while( i < 5 )    
        func(i),
    
    i++;
        
    for(i=0; i<3; i++)
    {
        for(j=0; j<3; j++)
        {
            cout << a[i][j] << endl;
        }
    }
    
    (i, j) = 6;//j=6
    
    cout << "i = " << i << endl;
    cout << "j = " << j << endl;

    return 0;
}
/*
func() : i = 0
func() : i = 1
func() : i = 2
func() : i = 3
func() : i = 4
2
5
8
0
0
0
0
0
0
i = 3
j = 6

*/

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

实验-重载逗号操作符的问题

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int mValue;
public:
    Test(int i)
    {
        mValue = i;
    }
    int value()
    {
        return mValue;
    }
};
/* case2:
Test& operator , (const Test& a, const Test& b)
{
    return const_cast<Test&>(b);
}
*/
Test func(Test& i)
{
    cout << "func() : i = " << i.value() << endl;
    
    return i;
}

int main()
{   
    Test t0(0);
    Test t1(1);
 //Test tt=(t0,t1);
   // Test tt = (func(t0), func(t1));  case1 调用默认逗号     
    //Test tt = (func(t0), func(t1));  //case2        (operator , (func(t0), func(t1)) ) 等价于 (func(t0), func(t1))
    Test tt = func(t1);//case3
    cout << tt.value() << endl; // 1
    
    return 0;
}
/*
case1:未手动重载逗号
func() : i = 0
func() : i = 1
1
case2:手动重载逗号
func() : i = 1
func() : i = 0
1

func() : i = 1
1

*/

小结

在这里插入图片描述

第40课 - 前置操作符和后置操作符

i++; ++i;
的值作为返回值,i自增自增 1,i 的值作为返回值
//i
下面的代码有没有区别?为什么?

实验-vs2010反汇编

    int i = 0;
000C139E  mov         dword ptr [i],0  

    i++;
000C13A5  mov         eax,dword ptr [i]  
000C13A8  add         eax,1  
000C13AB  mov         dword ptr [i],eax  

    ++i;
000C13AE  mov         eax,dword ptr [i]  
000C13B1  add         eax,1  
000C13B4  mov         dword ptr [i],eax 

实验-重载自增操作符

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int mValue;
public:
    Test(int i)
    {
        mValue = i;
    }
    
    int value()
    {
        return mValue;
    }
    
    Test& operator ++ ()//前置++
    {
        ++mValue;
        
        return *this;
    }
//无后置重载 报错error: no 'operator++(int)' declared for postfix '++' [-fpermissive]
/*
void operator++(int)//编译通过了
{

}*/
Test operator++(int)//优化
{
Test res=*this;//Test res(mValue);//先取值
mValue++;      //再加一
return res;

}
/*
    
    Test operator ++ (int)//后置++
    {
        Test ret(mValue);
        
        mValue++;
        
        return ret;
    }*/
};

int main()
{
    Test t(0);

  

cout<<"t="<<t.value()<<endl;
    
   Test tt= t.operator++(); //Test tt=++t;
cout<<"tt="<<tt.value()<<endl;

cout<<"t="<<t.value()<<endl;
  //前置++ ok
/*
t=0
tt=1
t=1
*/

   // t++;// error: no 'operator++(int)' declared for postfix '++' [-fpermissive]t++;
   // t.operator ++ ();
 Test h(0);

  

cout<<"h="<<h.value()<<endl;
    
   //Test hh=h.operator++(2); //Test hh=h++;
  Test hh=h.operator++(0); //占位参数
cout<<"hh="<<hh.value()<<endl;

cout<<"h="<<h.value()<<endl;
    
    return 0;
}

完善复数类:自增重载

Complex& operator++()
{
a++;
b++;
return *this;

}
Complex operator++(int)
{
Complex ret=*this;//Complex ret(a, b);
a++;
b++;
return ret;

}

小结

在这里插入图片描述

第41课 - 类型转换函数(上)

在这里插入图片描述

实验-隐式类型转换

#include <string>

using namespace std;

int main()
{   
    short s = 'a';
    unsigned int ui = 1000;
    int i = -2000;
    double d = i;
    
    cout << "d = " << d << endl;
    cout << "ui = " << ui << endl;
    cout << "ui + i = " << ui + i << endl;
    
    if( (ui + i) > 0 )
    {
        cout << "Positive" << endl;
    }
    else
    {
        cout << "Negative" << endl;
    }
    
    cout << "sizeof(s + 'b') = " << sizeof(s + 'b') << endl;//编译器并没有隐式转为short
    
    return 0;
}
/*
d = -2000
ui = 1000
ui + i = 4294966296
Positive
sizeof(s + 'b') = 4  */

在这里插入图片描述

实验-类类型与int相互转换

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int mValue;
public:
    Test()
    {
        mValue = 0;
    }
 /*
explicit Test(int i)
    {
        mValue = i;
    }*/
    
    Test(int i)
    {
        mValue = i;
    }
    
    Test operator + (const Test& p)
    {
        Test ret(mValue + p.mValue);
        
        return ret;
    }/**/
    
    int value()
    {
        return mValue;
    }
};

int main()
{   
    Test t;
    
    //类类型转换为int
   t = static_cast<Test>(5);    // t = Test(5);
    
    
    
    Test r;
    

r = t + 10;//未explicit 构造函数,调用重载,自动隐式转换,r.value()=15,要避免
       // r = t + static_cast<Test>(10);   
//r = t + Test(10);
    cout << r.value() << endl;
    
    return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

小结

在这里插入图片描述

第42课 - 类型转换函数(下)

在这里插入图片描述
在这里插入图片描述

实验-类型转换函数operator

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int mValue;
public:
    Test(int i = 0)
    {
        mValue = i;
    }
    int value()
    {
        return mValue;
    }
    operator int ()//类型转换函数
    {
        return mValue;
    }
};

int main()
{   
    Test t(100);
    int i = t;
    
    cout << "t.value() = " << t.value() << endl;   //t.value() = 100

    cout << "i = " << i << endl;                         //i = 100
    
    return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实验-类型转换成员函数

#include <iostream>
#include <string>

using namespace std;

class Test;

class Value
{
public:
    Value()
    {
    }
    explicit Value(Test& t)//
    {
    }
};

class Test
{
    int mValue;
public:
    Test(int i = 0)
    {
        mValue = i;
    }
    int value()
    {
        return mValue;
    }
    operator Value()//Value ToValue()
    {
        Value ret;
        cout << "operator Value()" << endl;
        return ret;
    }
};

int main()
{   
    Test t(100);
    Value v = t;//Value v = t.ToValue();
    
    return 0;
}
//operator Value()

在这里插入图片描述

小结

在这里插入图片描述

  • 13
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值