C字符串函数的包装类有问题吗?

时间:2011-08-04 09:46:06

标签: c++

我有一些用C风格编写的C ++代码 由于某些原因,我无法使用C ++字符串和IO库,因此对于字符串处理,我应该只使用sprintfitoa等函数。

我想替换需要临时缓冲区的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 当我们没有空闲堆内存时,通常我们仍然有一些千字节的堆栈(例如写入用户我们内存不足然后进行适当的清理)。

2 个答案:

答案 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()完成。

参考此msdn document

示例部分(示例2

下面,

const char* someMeaningfulName = i2a(x);
set_some_text(someMeaningfulName);

这不起作用,临时对象将在第一个语句本身释放。 someMeaningfulName将是垃圾。如果您觉得缺乏安全性,我只能说:

  

这就是微软的做法!