将指针分配给临时对象--如何防止它

Assigning a pointer to a temporary object -- how to prevent it?

本文关键字:何防止 临时对象 指针 分配      更新时间:2023-10-16

我的类有一个具有以下原型的方法:

std::string
Block::get_field(std::string rec_type, std::string field) { ... }

它从映射中检索一个值,将其转换为字符串,然后返回字符串。

有人用我的课如下:

char * buf = block.get_field(my_rec, my_field).c_str();

除非我弄错了,否则这是将buf设置为指向一个临时字符串。没过多久,当他看到*buf时,它就坏了。

显然,我更喜欢我的用户写:

std::string buf = block.get_field(my_rec, my_field);

作为Block的作者,我该如何防止这样的滥用行为?或者有没有一种方法可以让我以某种方式支持这种用法?

UPDATE 1:直到我将映射的实现从直接保存值更改为保存"内存引用"(一个长度和一个指向缓冲区的指针),这个错误才被发现。但是get_field总是返回一个字符串,而不是string*string&,所以我假设它总是返回一条临时字符串。我不明白为什么它之前没有中断(我也很尴尬;我声称我的更改不会影响API)。

我准备通知用户,他必须修改他的代码,但我希望能够引用他违反的"规则",并可能解释他之前是如何"运气好"的。

更新2:似乎有可能(参考更新1),刚才出现错误的原因是我的"隐藏"更改要求我在g++4.4.7中添加以下开关:-std=gnu++0x,这可能影响了临时资源的回收方式。

大多数情况下,您必须假设代码的用户是称职的。

但这是一个政治世界。因此,有时你可能不得不尽可能多的概率来防止事故的发生。例如,

#include <assert.h>
#include <string>
class StdString: public std::string
{
private:
using std::string::c_str;
using std::string::data;
public:
StdString( char const* const s ): std::string( s ) { assert( s != nullptr ); }
};
StdString foo() { return "Bah!"; }
int main()
{
std::string const   a = foo();
char const* const   b = foo().c_str();      //! Nyet.
}

也许可以在那里加入一个移动构造函数,但通常完美的效率与完美的安全性和完美的清晰度相冲突,例如可以有2个,但不能有3个。

你真的不应该阻止它,但如果你看到这种情况经常发生,你可以将原型更改为:

void
Block::get_field(std::string& ret, std::string rec_type, std::string field) { ... }

引用:std::string& ret将在调用方法之前强制std::字符串存在,尽管他们仍然可以破坏内存,但这将发生在"他们的代码"中。像这个坏代码这样简单的东西很难防止:

char * foo()
{
std::string buffStr;
block.get_field(bufStr, my_rec, my_field)
return buffStr.c_str();         // DO NOT DO THIS - Example of bad code
}

但至少mem检查器会找到他们的分配,而不是你的

UPDATE 1:c_str()返回的内存的生存期是生成它的string的生存期,除非string发生了更改,在这种情况下,生存期可能会结束。基本上,这是一种未定义的行为,有时可能有效,而其他情况则不然。您的更改可能已经改变了观察到的行为,但用户代码在任何时候都是一致的。其他因素也可能破坏它。基本上,它总是坏了,从你的描述来看,似乎没有理由道歉。