67-经典问题解析五

1、问题1

这里写图片描述

2、

这里写图片描述
当存在多个函数重载函数时:
编译器优先调用:
1、普通函数的重载
2、函数模板的重载
3、最后在调用可变参数的函数

#include <iostream>
#include <string>

using namespace std;

void test(int i)
{
    cout << "void test(int i)" << endl;
}

template
< typename T>
void test(T v)
{
    cout << "template void test(T v)" << endl;
}

void test(...)//最后被匹配调用
{
    cout << "void test(...)" << endl;
}

int main()
{
    int i = 0;
    test(i);

    return 0;
}
void test(int i)
3、

这里写图片描述

4、

这里写图片描述
利用函数重载 来区分是不是 指针;
1、将指针类型作为函数模板的参数
2、可变参函数作为接受非指针的函数(在函数重载时,可变参函数最后才匹配)

#include <iostream>
#include <string>

using namespace std;

class Test
{
public:
    Test()
    {
    }
    virtual ~Test()
    {
    }
};

template
<typename T>
bool IsPtr(T* v) // match pointer
{
    return true;
}

//可变参数函数,无法解决自定义类型的参数,比如类的对象
bool IsPtr(...)  // match non-pointer
{
    return false;
}



int main(int argc, char *argv[])
{
    int i = 0;
    int* p = &i;

    cout << "p is a pointer: " << IsPtr(p) << endl;    // true
    cout << "i is not a pointer: " << IsPtr(i) << endl;    // false

    Test t;
    Test* pt = &t;

    cout << "pt is a pointer: " << IsPtr(pt) << endl;    // true
    cout << "t is not a pointer: " << IsPtr(t) << endl;    // false
        return 0;
}

p is a pointer: 1
i is not a pointer: 0
pt is a pointer: 1
非法指令 
//warning: cannot pass objects of non-POD type 'class Test' through '...'; call will abort at runtime

//但是有的编译器 最后的变参数函数能够正确的执行(不知道为什么)
//正常输出t is not a pointer: 0
5、

这里写图片描述
sizeof 关键字可以计算函数的返回值大小,确不会执行函数内容,这点解决了上述可变参函数对自定义类型参数的解析
(要想变参函数不调用,只匹配只能用sizeof());

#include <iostream>
#include <string>

using namespace std;

class Test
{
public:
    Test()
    {
    }
    virtual ~Test()
    {
    }
};

template
<typename T>
char IsPtr(T* v) // match pointer
{
    return 'd';//是指针的话,返回一个字节
}

int IsPtr(...)  // match non-pointer
{
    return 0;//不是指针的话,返回4个字节
}
//定义一个宏,宏中利用sizeof判断函数的返回值不同来确定是否为指针
#define ISPTR(p) (sizeof(IsPtr(p)) == sizeof(char))

int main(int argc, char *argv[])
{
    int i = 0;
    int* p = &i;

    cout << "p is a pointer: " << ISPTR(p) << endl;    // true
    cout << "i is not a pointer: " << ISPTR(i) << endl;    // false

    Test t;
    Test* pt = &t;

    cout << "pt is a pointer: " << ISPTR(pt) << endl;    // true
    cout << "t is not a pointer: " << ISPTR(t) << endl;    // false

    return 0;
}
p is a pointer: 1
i is not a pointer: 0
pt is a pointer: 1
t is not a pointer: 0
6、问题2

这里写图片描述

7、构造函数中抛出异常

这里写图片描述

#include <iostream>
#include <string>

using namespace std;

class Test
{
public:
    Test()
    {
        cout << "Test()" << endl;

        throw 0;//在构造函数中抛出异常
    }
    virtual ~Test()
    {
        cout << "~Test()" << endl;
    }
};


int main(int argc, char *argv[])
{
    Test* p = reinterpret_cast<Test*>(1);
    //初始化指针p的值为1,为了验证test对象没有被创建成功,p没有被赋值,

    try
    {
        p = new Test();
    }
    catch(...)
    {
        cout << "Exception..." << endl;
    }

    cout << "p = " << p << endl;

    return 0;
}
Test()
Exception...
p = 0x1
很显然 new Test()并没有创建成功,在构造函数中,打印一条语句后,就抛出异常,通过catch将异常捕获,并没有赋值给p,对象没有创建成功
也就不会调用析构函数,对象所占用的空间被收回,不会造成内存泄漏
Linux 下 valgrind 内存泄漏工具使用
g++ -g test.cpp
valgrind --tool=memcheck --leak-check=full ./a.out

==23025== Memcheck, a memory error detector
==23025== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==23025== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==23025== Command: ./a.out
==23025== 
Test()
Exception...
p = 0x1
==23025== 
==23025== HEAP SUMMARY:
==23025==     in use at exit: 72,704 bytes in 1 blocks
==23025==   total heap usage: 4 allocs, 3 frees, 73,868 bytes allocated
==23025== 
==23025== LEAK SUMMARY:
==23025==    definitely lost: 0 bytes in 0 blocks
==23025==    indirectly lost: 0 bytes in 0 blocks
==23025==      possibly lost: 0 bytes in 0 blocks
==23025==    still reachable: 72,704 bytes in 1 blocks
==23025==         suppressed: 0 bytes in 0 blocks
==23025== Reachable blocks (those to which a pointer was found) are not shown.
==23025== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==23025== 
==23025== For counts of detected and suppressed errors, rerun with: -v
==23025== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
8、

这里写图片描述

9、

这里写图片描述

1)如果析构函数抛出异常,则异常点之后的程序不会执行,如果析构函数在异常点之后执行了某些必要的动作比如释放某些资源,则这些动作不会执行,会造成诸如资源泄漏的问题。
2)通常异常发生时,c++的机制会调用已经构造对象的析构函数来释放资源,此时若析构函数本身也抛出异常,则前一个异常尚未处理,又有新的异常,会造成程序崩溃的问题。
3)那么当无法保证在析构函数中不发生异常时, 该怎么办?
那就是把异常完全封装在析构函数内部,决不让异常抛出函数之外。
10、小结

这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值