13

我有一个相当基本的 C++ 问题:考虑一个函数,它接受一些输入参数并std::string从这些参数创建一个,如下所示:

std::string constructString( int some_parameter ) {
    
    std::stringstream ss;
    
    // Construct a string (arbitrarily complex)
    ss << "Some parameter is " << some_parameter << " right now";

    return ss.str();    //Am I not returning a temporary object here?
}

我知道stringstream当函数返回时对象将超出范围,但这不会使构造的字符串也无效吗?

如果我将返回类型更改为const char *并返回,会发生什么ss.str().c_str()

上面的代码似乎可以工作,但我怀疑这只是因为包含“临时”对象的内存在我使用它时还没有被其他东西覆盖?

我不得不承认,一般来说,我在这种情况下很困惑。如果有人可以向我解释这整个“临时对象”的事情(或者只是指出我正确的方向),我将不胜感激。

4

3 回答 3

19

您正在返回一个临时对象,但是因为您按值返回它,所以创建了副本。如果您返回指向临时对象的指针或引用,那将是一个错误。

如果您将返回类型更改为const char *并返回ss.str().c_str(),您将返回指向临时std::string返回的某个缓冲区的指针ss.str(),这会很糟糕。

于 2012-10-18T10:18:46.873 回答
5

如您所见, Stringstream::str()返回std::string对象。您返回时std::string没有引用,这意味着如果没有 RVO(NRVO) 优化,复制构造函数将调用并创建有效std::string对象。使用优化std::string将在没有复制构造函数的情况下移动。但是如果将返回std::string&它会崩溃,因为这个对象将在函数返回后被销毁。效果相同,const char *因为销毁此指针后将指向坏内存,这是危险的情况。

于 2012-10-18T10:21:07.883 回答
1

假设:T val = some_function(),当您使用指定的复制构造函数或内置运算符从some_functionC++ 复制值返回值时。val因此,如果您返回一个intstd::string根本没有问题,但是如果您返回一个指向将在函数结束时释放的内存的指针,哎呀!您的指针将指向无效的内存。例如考虑这个:

const char* some_function() {
    std::string res( ... );
    //...
    return res.c_str();
}

您正在返回指向将在函数返回后立即释放的数据的指针(因为res将被销毁并且它将释放其内部数据),因此您将获得地址,但该地址并不指向您可能期望的!

于 2012-10-18T10:26:21.193 回答