为什么在返回字符串的函数上调用std :: string.c_str()无效?

哈克索伊

我有以下代码:

std::string getString() {
    std::string str("hello");
    return str;
}

int main() {
    const char* cStr = getString().c_str();
    std::cout << cStr << std::endl; // this prints garbage
}

我以为会发生的是,getString()将返回一个复制strgetString()按价值计算收益); 因此,的副本str将保持“活动”状态main()直到main()返回。这将cStr指向一个有效的内存位置:所返回的副本的基础char[]char*(或任何形式)保留在中strgetString()main()

但是,显然不是这种情况,因为程序会输出垃圾。因此,问题是,什么时候被str销毁,为什么?

songyuanyao

getString()将返回strgetString()按值返回)的副本

这是正确的。

因此,的副本str将保持“活动”状态main()直到main()返回。

不,返回的副本是一个临时副本std::string,它将在创建该副本的语句末尾(即before)销毁std::cout << cStr << std::endl;然后cStr变得悬而未决,对其取消引用会导致UB,一切皆有可能。

您可以将返回的临时变量复制到命名变量,或将其绑定到constlvalue-reference或rvalue-reference(临时变量的寿命将延长,直到引用超出范围)。如:

std::string s1 = getString();    // s1 will be copy initialized from the temporary
const char* cStr1 = s1.c_str();
std::cout << cStr1 << std::endl; // safe

const std::string& s2 = getString(); // lifetime of temporary will be extended when bound to a const lvalue-reference
const char* cStr2 = s2.c_str();
std::cout << cStr2 << std::endl; // safe

std::string&& s3 = getString();  // similar with above
const char* cStr3 = s3.c_str();
std::cout << cStr3 << std::endl; // safe

这是[The.C ++。Programming.Language.Special.Edition] 10.4.10临时对象[class.temp]的解释

除非绑定到引用或用于初始化命名对象,否则临时对象将在创建该对象的完整表达式的末尾销毁。完整表达式是不是其他表达式的子表达式的表达式。

标准字符串类具有成员函数c_str(),该函数返回C样式,零终止字符数组(第3.5.1节,第20.4.1节)。同样,运算符+被定义为表示字符串连接。这些是用于字符串的非常有用的工具。但是,它们结合在一起可能会引起难以理解的问题。例如:

void f(string& s1, string& s2, string& s3)
{

    const char* cs = (s1 + s2).c_str();
    cout << cs ;
    if (strlen(cs=(s2+s3).c_str())<8 && cs[0]==´a´) {
        // cs used here
    }

}

您的第一个反应可能是“但不要那样做”,我同意。但是,此类代码确实可以编写,因此值得了解如何解释。

将创建一个类字符串的临时对象来容纳s1 + s2。接下来,从该对象提取指向C样式字符串的指针。然后-在表达式的末尾-删除临时对象。现在,C风格的字符串分配在哪里?可能是临时对象s1 + s2的一部分,并且在该临时对象被销毁后不能保证存在该存储。因此,cs指向释放的存储。输出操作cout << cs可能会按预期工作,但这真是运气。编译器可以检测到此问题并针对此问题发出警告。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么在返回字符串的函数上调用c_str()无效?

来自分类Dev

std::string 的 c_str() 函数如何返回空终止字符串?

来自分类Dev

为什么在动态分配字符串时string :: c_str()返回const char *?

来自分类Dev

std::string::c_str() 可以返回 nullptr 吗?

来自分类Dev

临时字符串上string :: c_str的用法

来自分类Dev

从函数返回的std :: string上直接调用c_str()是否安全?

来自分类Dev

std :: string :: c_str()覆盖了函数返回的前一个

来自分类Dev

std :: move on std :: string garantee是否使.c_str()返回相同结果?

来自分类Dev

c_str ==字符串与c_str == c_str的值相等

来自分类Dev

如何为std :: string可变参数模板参数调用c_str()?

来自分类Dev

使用const_cast <char *>()将std :: string :: c_str()的结果传递给mkdtemp()。

来自分类Dev

字符串的c_str()函数的C ++奇怪行为

来自分类Dev

使用c_str()返回的指针删除动态分配的std :: string是否会导致C ++中的内存泄漏?

来自分类Dev

c_str()返回空字符串

来自分类Dev

std :: vector <std :: basic_string <char>> :: const_iterator'没有名为'c_str'的成员

来自分类Dev

链接器错误-带有libboost_thread的macOS上未定义的符号std :: string :: c_str()const?

来自分类Dev

递归std :: stringstream和c_str

来自分类Dev

递归std :: stringstream和c_str

来自分类Dev

为什么不可变字符串可以调用String :: add(mut self,other:&str)

来自分类Dev

字符串类的c_str实现

来自分类Dev

在UTF8中将System :: String转换为std :: string,随后将其转换为char *作为c_str

来自分类Dev

为什么C ++字符串不需要std :: forward来调用所需的函数?

来自分类Dev

C ++字符串返回和c_str()强制转换的混乱行为

来自分类Dev

'std :: basic_string <char,std :: char_traits <char>,std :: allocator <char >> :: c_str':非标准语法; 使用“&”创建指向成员的指针

来自分类常见问题

c_str()不返回任何内容,但字符串不为空

来自分类Dev

c_str()不返回任何内容,但字符串不为空

来自分类Dev

在C ++中将字符串文字传递给接受const std :: string&的函数时会发生什么?

来自分类Dev

为什么std :: string :: substr抛出异常而不是返回空字符串?

来自分类Dev

为什么data()和c_str()返回char const *,而operator []返回char&?

Related 相关文章

  1. 1

    为什么在返回字符串的函数上调用c_str()无效?

  2. 2

    std::string 的 c_str() 函数如何返回空终止字符串?

  3. 3

    为什么在动态分配字符串时string :: c_str()返回const char *?

  4. 4

    std::string::c_str() 可以返回 nullptr 吗?

  5. 5

    临时字符串上string :: c_str的用法

  6. 6

    从函数返回的std :: string上直接调用c_str()是否安全?

  7. 7

    std :: string :: c_str()覆盖了函数返回的前一个

  8. 8

    std :: move on std :: string garantee是否使.c_str()返回相同结果?

  9. 9

    c_str ==字符串与c_str == c_str的值相等

  10. 10

    如何为std :: string可变参数模板参数调用c_str()?

  11. 11

    使用const_cast <char *>()将std :: string :: c_str()的结果传递给mkdtemp()。

  12. 12

    字符串的c_str()函数的C ++奇怪行为

  13. 13

    使用c_str()返回的指针删除动态分配的std :: string是否会导致C ++中的内存泄漏?

  14. 14

    c_str()返回空字符串

  15. 15

    std :: vector <std :: basic_string <char>> :: const_iterator'没有名为'c_str'的成员

  16. 16

    链接器错误-带有libboost_thread的macOS上未定义的符号std :: string :: c_str()const?

  17. 17

    递归std :: stringstream和c_str

  18. 18

    递归std :: stringstream和c_str

  19. 19

    为什么不可变字符串可以调用String :: add(mut self,other:&str)

  20. 20

    字符串类的c_str实现

  21. 21

    在UTF8中将System :: String转换为std :: string,随后将其转换为char *作为c_str

  22. 22

    为什么C ++字符串不需要std :: forward来调用所需的函数?

  23. 23

    C ++字符串返回和c_str()强制转换的混乱行为

  24. 24

    'std :: basic_string <char,std :: char_traits <char>,std :: allocator <char >> :: c_str':非标准语法; 使用“&”创建指向成员的指针

  25. 25

    c_str()不返回任何内容,但字符串不为空

  26. 26

    c_str()不返回任何内容,但字符串不为空

  27. 27

    在C ++中将字符串文字传递给接受const std :: string&的函数时会发生什么?

  28. 28

    为什么std :: string :: substr抛出异常而不是返回空字符串?

  29. 29

    为什么data()和c_str()返回char const *,而operator []返回char&?

热门标签

归档