繁体   English   中英

临时对象的销毁究竟何时在函数调用中发生?

[英]When exactly does the destruction of a temporary object happen in a function call?

此代码编译并执行。 我知道在第一种情况下我们有未定义的行为。 但是在第二种情况下到底发生了什么?

#include <string>
#include <iostream>
#include <cstdio>

std::string foo() {
    return "HELLO";
}

void bar(const char *p) {
    std::printf("%s\n", p);
}


int main() {

    // FIRST CASE:
    // I know this is bad, because after the assignment
    // the variable returned by foo() is destroyed and we
    // have a bad reference.
    const std::string &s = foo(); 
    bar(s.c_str());


    // SECOND CASE:
    // But what about that ? I don't know exactly if the 
    // object is alive after the call to c_str() 
    bar(foo().c_str());

    return 0;
}

GCC 输出在两种情况下都是“HELLO”,但我认为这是因为它没有清理原始内存。

在第二种情况下,临时对象究竟何时被销毁?

其实这两种情况都可以。

在第一种情况下,将临时对象绑定到const引用会将其生命周期扩展到s生命周期。 所以它不会被销毁,直到main出口。

在第二种情况下,临时对象在包含它的完整表达式结束后被销毁。 在这种情况下,它是函数调用。 如果您将该 C 字符串存储在比bar寿命更长的任何位置,然后尝试访问它,那么您的到期日期将是未定义的行为。

这两种情况都是明确定义的。 要查看有问题的情况,请存储c_str()的结果,直到std::string被破坏:

#include <string>
#include <cstdio>

std::string foo() {
    return "HELLO";
}

void bar(const char *p) {
    std::printf("%s\n", p);
}

int main() {
    {
        // FIRST CASE:
        // This is okay, because the reference is const, so the object is alive
        // until s goes out of scope.
        const std::string &s = foo();
        bar(s.c_str());
    }

    {
        // VARIANT FIRST CASE:
        // This is bad; the pointer is dangling
        const char *s = foo().c_str();
        bar(s);
    }

    {
        // SECOND CASE:
        // Is the object still alive after the call to c_str()?  Yes, it's alive
        // until after bar() has returned.
        bar(foo().c_str());
    }

    return 0;
}

当我在 Valgrind 下运行它时,它仅针对变体情况(使用const char *s )给出错误:

==9981== Invalid read of size 1
==9981==    at 0x4C2E0E2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9981==    by 0x543EC7B: puts (ioputs.c:36)
==9981==    by 0x400937: bar(char const*) (37946437.cpp:9)
==9981==    by 0x4009AA: main (37946437.cpp:25)
==9981==  Address 0x5aabcf8 is 24 bytes inside a block of size 30 free'd
==9981==    at 0x4C2C2BC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9981==    by 0x4F058FD: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.22)
==9981==    by 0x40099E: main (37946437.cpp:24)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM