我有一些用C风格编写的C ++代码
由于某些原因,我无法使用C ++字符串和IO库,因此对于字符串处理,我应该只使用sprintf
,itoa
等函数。
我想替换需要临时缓冲区的C风格 char buf [12]; itoa(x,buf,16); set_some_text(BUF);
通过以下代码
class i2a
{
public:
explicit i2a(int value) { ::sprintf(buf, "%d", value); }
operator const char* () const { return buf; }
private:
char buf[12];
};
// usage:
set_some_text(i2a(x));
(此类可以为char<->wchar_t
转换等编写。)
我看到这些类很危险的情况: 例如,可以写
const char* someMeaningfulName = i2a(x);
// the right code should be i2a someMeaningfulName(x); or i2a someMeaningfulName = i2a(x);
set_some_text(someMeaningfulName);
在更复杂的情况下,接受文本的函数不会复制它,但会在某处保存指向它的指针。例如,它可能是
class Foo { .... const char* p; };
Foo f(const char* text) { ... foo.p = text; return foo; }
与const char*
变量不同,它可能真的不明显。
有没有办法让这些课程更安全?
更新:为什么不用std :: string,boost :: lexical_cast,boost :: format等:
使用-fno-except编译代码时应该工作(禁用C ++异常 - 没有throw
,没有堆栈展开)。此外,它应该继续在低内存条件下工作
std::string
,流使用堆分配的内存,至少抛出bad_alloc
当我们没有空闲堆内存时,通常我们仍然有一些千字节的堆栈(例如写入用户我们内存不足然后进行适当的清理)。
答案 0 :(得分:0)
如果对局部变量使用const char *,那么总会遇到麻烦。 你将拥有与const char *相同的someMeaningfulName = std :: string(“foo”)。c_str();
如果可以的话,你应该声明你的本地变量:
i2a someMeaningfulName(x);
set_some_text(someMeaningfulName);
您还可以考虑向i2a添加复制构造函数,以避免在两个实例之间共享缓冲区。
答案 1 :(得分:0)
ATL和MFC字符串转换宏也是以这种方式编写的。像i2a(x)
一样直接调用构造函数将创建一个临时对象,该对象将一直存在,直到传递它的函数完成为止。所以这里:do_some(i2a(x))
,临时对象将在那里,直到do_some()
完成。
下面,
const char* someMeaningfulName = i2a(x);
set_some_text(someMeaningfulName);
这不起作用,临时对象将在第一个语句本身释放。 someMeaningfulName
将是垃圾。如果您觉得缺乏安全性,我只能说:
这就是微软的做法!