我目前正在将一个相当大的项目从 VS 2008 转换为 2012,并且在似乎执行条件运算符类型转换的方式上遇到了问题。
首先让我说我接受条件运算符的语义有些复杂,并意识到代码最初所做的可能不正确,但我真的对 VS 2012 中现在发生的事情感到困惑,我想知道是否有人可以准确解释为什么它会这样做。
class DummyString
{
wchar_t wchBuf[32];
public:
DummyString() { *wchBuf = 0; }
DummyString(int) { *wchBuf = 0; }
DummyString(const DummyString& ds) { *wchBuf = 0; }
operator const wchar_t*() const { return wchBuf; }
};
int _tmain(int argc, _TCHAR* argv[])
{
DummyString ds;
// note: the argc test is simply to stop the conditional operator
// being optimised away
const wchar_t* pPtr = (argc == 100) ? 0 : ds;
assert(pPtr == static_cast<const wchar_t*>(ds));
return 0;
}
在 VS 2008 中,上面的条件运算符将导致operator const wchar_t*()
方法被调用ds
并且断言不会触发。也就是说,它将隐式ds
转换为 a const wchar_t*
。
在 VS 2012 中,条件运算符导致以下行为:
DummyString
通过复制构造函数构造一个临时的const wchar_t*
然后在该临时副本上执行转换为
这导致pPtr
指向一个被破坏的对象,并且断言当然会触发。
现在,如果我DummyString(int)
从类中删除构造函数,则代码无法在 VS2012 中编译(没有从 'DummyString' 到 'int' 的转换),所以很明显,条件中的0导致表达式被评估为 int 而不是指针.
但是在那种情况下,为什么不DummyString(int)
调用构造函数将 0 转换为 a DummyString
?为什么编译器创建一个副本ds
然后将其转换为 wchar_t*,而它可以很容易地对原始对象执行转换?
我很想开悟!:)