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

Is something wrong with wrapper classes for C string functions?

本文关键字:有问题 包装 字符串 函数      更新时间:2023-10-16

我有一些用C风格写的c++代码。
由于某些原因,我不能使用c++字符串和IO库,所以对于字符串处理,我应该只使用sprintf, itoa等函数。

我想替换需要临时缓冲区的c风格char buf [12];Itoa (x, but, 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*变量。

有没有办法使这样的类更安全?


Upd:为什么不std::string, boost::lexical_cast, boost::format等:
当使用-fno-except编译时,代码应该可以工作(禁用c++异常-没有throw,没有堆栈展开)。而且它应该在低内存条件下保持工作。
std::string,流使用堆分配内存,至少抛出bad_alloc
当我们没有空闲的堆内存时,通常我们仍然有一些kb的堆栈(例如,向用户写内存不足,然后进行适当的清理)。

ATL和MFC字符串转换宏也以这种方式编写。像i2a(x)一样直接调用构造函数将创建一个临时对象,该对象将一直存在,直到传递给它的函数完成。所以这里:do_some(i2a(x)),临时对象将在那里直到do_some()完成。

参考msdn文档

Example部分( Example 2)

,

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

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

微软就是这么做的!

如果对局部变量使用const char*,总是会遇到麻烦。const char* someemeaningfulname = std::string("foo").c_str();

如果可以,你应该这样声明你的局部变量:

i2a someMeaningfulName(x);
set_some_text(someMeaningfulName);

您还可以考虑为i2a添加复制构造函数,以避免在两个实例之间共享缓冲区。