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

C++: use std::string returned by a function: Using pointer to local variable that is out of scope

我有以下功能:

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..

}

所以,问题是,如何在 if 子句的范围之外“延长”temporaryString 的生命周期?

目前,我收到以下错误:

Using pointer to local variable 'temporary' that is out of scope.

我知道这与内存管理有关,并且 temporary 被假定为在 if 子句之后被“销毁”或从内存中清除的事实。但是我需要延长它的生命周期,或者创建另一个具有不同的、更广泛范围的字符串(副本)。

我怎样才能做到这一点?

要求:

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

static 存储可能就是您正在寻找的。 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;
    }   
}

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

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

Who will allocate the memory of the passed string and who is responsible to free that memory.

选项:

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

顺便说一句:保持损坏的接口是不良软件的良好起点:-)在给定的情况下,如果空字符串也有效,您将开始使用数组中的标志和所有损坏的东西进行黑客攻击(通常我们应该使用结构带有已经用 std::optional 定义的标志。

只需将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最初是空白的,在函数退出时被销毁,因此重新分配的value在函数运行期间仍然有效,只要temporaryString未修改。