C++隐式转换的那些事

昨天在公司干活的时候遇到一个C++隐式转换的问题, 折腾了很久, 后来碰巧发现了一丝线索, 才得以解决. 废话不多说了, 先上代码:

 

// 此数组模板类声明
template
class SomeArray {

SomeArray(int physicalLength = 32, int growLength = 32);
...

int append(const T& value);
AcArray& append(const AcArray& otherArray);

...
};

// 枚举类型
enum Format { kFirst, ..., kLast };

// 问题代码
SOME_FUNC(...) {
    ...
    SomeArray<Format> fmtArray;
    ...
    for (int fmt = kFirst; fmt <= kLast; ++fmt) {
        if (fmt satisfy some condition) fmtArray.append(fmt);
    }
}

 

   上述问题代码在执行循环的时候, 明明append元素这条语句执行了, 但是fmtArray仍然为空. 于是我就在这条语句处设置 了断点, 然后F11进去看. 结果发现跳转到了SomeArray的构造函数里. 然后我又尝试了几次, 发现还是如此. 我就纳闷, 难道我构建出来的二进制出错导致link不对? 不可能啊, 这是一个模板类, 不需要link啊. 又或者是因为这个模板类是编译在一个pch文件里, 那个文件被弄dirty了? 尝试了一下, 发现不是由于link或者pch导致的. 没办法了, 下班前, 开始做了一个fully clean build(2 ~ 3小时), 希望排除某些模块的dirty所导致的问题.

 

    今天上班后, 和同事J继续调试, 发现, 居然还是继续跳入构造函数. 构造函数调用完毕后, 退回到append元素语句处. 这时候奇迹发生了: 同事J手一不小心, 又按了一下F11, 结果, 居然跳入了append函数内部. 这个append函数并不是append一个元素, 而是一个SomeArray<Format> 对象, 但是这个对象是空的. 执行完毕这个函数后,  继续按F11, 结果跳到了SomeArray的析构函数. 到这里, 问题基本上已经很清楚了:

 

    由于fmt是一个整形值, 那么C++在解析重载append函数时, 由于Integer->Enumeration的转换不能自动进行, 所以编译器倾向于寻找一条更可行的转换链: int -> SomeArray<Format>, 因为默认构造函数支持这种转换. 于是, 你所append的每个元素, 都用来作为构建临时数组对象时所使用的physicalLength 参数值. 最终得到的fmtArray也因为append了一堆空数组而始终为空.

 

    从这个问题, 我得到两个结论:

       

         1. C++的类型转换的确诡异, 自己平时编写的时候, 一定要注意适当地使用explicit关键字,避免不必要的隐式转换.

 

         2. 遇到诡异的事情, 还是要沉着冷静, 利用已有的信息去进行深入的分析, 不放过每个可疑的线索.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值