C++:使用函数返回的std::字符串:使用指向超出范围的局部变量的指针



我有以下函数:

MyFunction(const char *value, bool trigger) {
if (trigger) {
std::string temporaryString = getTemporaryStringFromSomewhereElse();
value = temporaryString.c_str();
}
// do processing here
// I need `value` and `temporaryString.c_str();` to be alive and accessible here and not destroyed

MyClass *object = new MyClass(value);
object->Work();
// etc..
}

所以,问题是,我怎样才能";延长";temporaryString的生命周期是否在if-子句的范围之外?

目前,我得到以下错误:

使用指向超出范围的局部变量"temporary"的指针。

我理解这与内存管理有关,并且假设temporary是";销毁";或者在CCD_ 4-子句之后从存储器中清除。但我需要延长它的生命周期,或者创建另一个字符串(副本(,它将具有不同的、更广泛的范围。

我怎样才能做到这一点?

要求:

  1. 函数签名不能更改,应保留为:MyFunction(const char *value, bool trigger)
  2. 稍后我使用value初始化另一个对象,做一些其他工作。我不能有两个变量,例如valueanotherValueToBeUsedIfTriggerIsTrue

只需将std::string的声明从if块移到功能块中,例如:

MyFunction(const char *value, bool trigger) {
std::string temporaryString;
if (trigger) {
temporaryString = getTemporaryStringFromSomewhereElse();
value = temporaryString.c_str();
}
// do processing here

MyClass *object = new MyClass(value);
object->Work();
// etc..
}

std::string最初将为空,并在函数退出时销毁,因此,只要temporaryString未被修改,重新分配的value将在函数运行期间保持有效。

静态存储可能就是您要搜索的。变量的static属性将其生存时间扩展到整个程序执行时间。

void MyFunction(const char *value, bool trigger) {
if (trigger) {
static std::string s_buffer; // Note : this line is executed only once so don't assign the value here
s_buffer = getTemporaryStringFromSomewhereElse();
value = s_buffer.c_str();
}
// use of value is still correct even outside the if statement.
}

注意:在多线程程序的情况下,静态的使用不是线程安全的,对于这种情况,标准提供了thread_local存储。

在这种情况下,我更喜欢std::optional,因为它还显示是否设置了请求的对象。

示例:

std::string getTemporaryStringFromSomewhereElse()
{
return "Here I am";
}
std::optional< std::string > MyFunction(bool trigger) {
if (trigger) {
return getTemporaryStringFromSomewhereElse();
}   
return std::nullopt;
}
int main()
{
auto retval = MyFunction( true );
if ( retval )
{   
std::cout << *retval << std::endl;
}   
}

编辑:(在我们得到界面不可更改的信息后(

这最终导致了所有权问题!

谁将分配传递字符串的内存,谁负责释放该内存。

选项:

  1. 分配足够的空间,并将指向该内存的指针传递给函数,如果设置了触发器,则复制内容,或者将内存的第一个字符设置为零,以显示您传递回一个空字符串。如果也可以使用空字符串,则使用例如第一个或最后一个内存元素作为标志
  2. 分配函数内部的内存,复制给定的字符串并传回指针,如果未设置触发器,则返回nullptr。函数的调用方必须处理释放给定内存的问题
  3. 如果保证在第一次调用和内容使用之间不会再次调用函数,则函数本身可以保留一个静态数组,并将地址传回该静态内存

BTW:保留损坏的接口是坏软件的一个好的起点:-(在给定的情况下,如果空字符串也是有效的,你就开始用数组中的标志和所有损坏的东西进行黑客攻击(通常我们应该使用带有标志的structs,正如std::optional所定义的那样(。

最新更新