简体   繁体   English

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

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

This code compiles and executes.此代码编译并执行。 I know that we have undefined behaviour in the first case.我知道在第一种情况下我们有未定义的行为。 But what happens exactly in the second case?但是在第二种情况下到底发生了什么?

#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 output is in both cases "HELLO" but I think that's because it's not cleaning the raw memory. GCC 输出在两种情况下都是“HELLO”,但我认为这是因为它没有清理原始内存。

In the second case when exactly is the temporary object destroyed?在第二种情况下,临时对象究竟何时被销毁?

Actually, both of these cases are okay.其实这两种情况都可以。

In the first case, binding the temporary to a const reference extends its lifetime to that of s .在第一种情况下,将临时对象绑定到const引用会将其生命周期扩展到s生命周期。 So it won't be destroyed until main exits.所以它不会被销毁,直到main出口。

In the second case, the temporary is destroyed after the end of the full-expression containing it.在第二种情况下,临时对象在包含它的完整表达式结束后被销毁。 In this case, it is the function call.在这种情况下,它是函数调用。 If you stored that C string anywhere which outlived bar and then tried to access it, then you're due a date with undefined behaviour.如果您将该 C 字符串存储在比bar寿命更长的任何位置,然后尝试访问它,那么您的到期日期将是未定义的行为。

Both of those cases are well-defined.这两种情况都是明确定义的。 To see a problematic case, store the result of c_str() until after the std::string is destructed:要查看有问题的情况,请存储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;
}

When I run this under Valgrind, it gives errors only for the variant case (with const char *s ):当我在 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.

相关问题 将左值分配给右值引用时会发生什么? 没有破坏临时对象? - What happen when a lvalue assigned to a rvalue reference? No destruction of the temporary object? C++中临时对象的销毁 - Destruction of a temporary object in C++ 为什么下面代码中临时 object 的第二次销毁发生在“End of f”消息打印之前? - Why does the second destruction of the temporary object on the code below occurs before the message “End of f” is printed? 调用 [[noreturn]] function 和销毁顺序 - Call to a [[noreturn]] function and order of destruction 临时对象的生存期:在嵌套函数调用中迭代到临时向量 - Lifetime of temporary object: iterator to temporary vector in nested function call 标准C ++ 11是否保证在函数调用之前创建传递给函数的临时对象? - Does standard C++11 guarantee that temporary object passed to a function will have been created before function call? C ++临时对象的调用函数 - C++ Call function of a temporary object 在对临时函数对象的调用中解析歧义 - Parsing ambiguity in a call to a temporary function object 在对象销毁期间调用的函数 - Function, called during the object destruction C++ 使用复制构造函数避免临时 Object 破坏 - C++ Avoid Temporary Object Destruction using Copy Constructor
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM