Beware the C++ implicit conversion

 http://blogs.msdn.com/oldnewthing/archive/2006/05/24/605974.aspx and a lot of comments there.

Enjoy!

Beware the C++ implicit conversion

Today's topic was inspired by a question from a customer:

I am working on a stack overflow bug. To reduce the size of the stack frame, I removed as many local variables as I could, but there's still a a lot of stack space that I can't account for. What else lives on the stack aside from local variables, parameters, saved registers, and the return address?

Well, there's also structured exception handling information, but that's typically not too much and therefore wouldn't be the source of "a lot" of mysterious stack usage.

My guess is that the code is generating lots of large C++ temporaries. Consider the following program fragment:

class BigBuffer
{
public:
 BigBuffer(int initialValue)
   { memset(buffer, initialValue, sizeof(buffer)); }
private:
 char buffer[65536];
};

extern void Foo(const BigBuffer& o);

void oops()
{
 Foo(3);
}

"How does this code even compile? The function Foo wants a BigBuffer, not an integer!" Yet compile it does.

That's because the compiler is using the BigBuffer constructor as a converter. In other words, the compiler inserted the following temporary variable:

void oops()
{
 BigBuffer temp(3);
 Foo(temp);
}

It did this because a constructor that takes exactly one argument serves two purposes: It can be used as a traditional constructor (as we saw with BigBuffer temp(3)) or it can be used to provide an implicit conversion from the argument type to the constructed type. In this case, the BigBuffer(int) constructor is being used as a conversion from int to BigBuffer.

To prevent this from happening, use the explicit keyword:

class BigBuffer
{
public:
 explicit BigBuffer(int initialValue)
   { memset(buffer, initialValue, sizeof(buffer)); }
private:
 char buffer[65536];
};

With this change, the call to Foo(3) raises a compiler error:

sample.cpp: error C2664: 'Foo' : cannot convert parameter 1 from
     'int' to 'const BigBuffer &'
     Reason: cannot convert from 'int' to 'const BigBuffer'
     Constructor for class 'BigBuffer' is declared 'explicit'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值