C++,匿名(未命名)变量的对象生命周期

col*_*ole 4 c++

在下面的代码中,“main()”最后一行构造的对象似乎在表达式结束之前被销毁。析构函数在执行“<<”之前调用。这是应该的样子吗?

#include <string>
#include <sstream>
#include <iostream>

using std::string;
using std::ostringstream;
using std::cout;

class A : public ostringstream
{
public:
  A () {}
  virtual ~A ()
  {    
    string s;
    s = str();
    cout << "from A: " << s << std::endl;
  }
};

int
main ()
{
  string s = "Hello";
  A os;

  os << s;
  cout << os.str() << std::endl;

  A() << "checking this";
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

Hello
from A: 0x80495f7
from A: Hello
Run Code Online (Sandbox Code Playgroud)

这是 gdb 日志:

(gdb) b os.cxx : 18
Breakpoint 1 at 0x80492b1: file os.cxx, line 18. (2 locations)
(gdb) r
Starting program: /home/joe/sandbox/test/os 
Hello

Breakpoint 1, ~A (this=0xbffff37c, __in_chrg=<value optimized out>, __vtt_parm=<value optimized out>) at os.cxx:18
18     cout << "from A: " << s << std::endl;
(gdb) p s.c_str ()
$1 = 0x804b45c "0x80495f7"
(gdb) p *s.c_str ()
$2 = 48 '0'
(gdb) c
Continuing.
from A: 0x80495f7

Breakpoint 1, ~A (this=0xbffff2bc, __in_chrg=<value optimized out>, __vtt_parm=<value optimized out>) at os.cxx:18
18     cout << "from A: " << s << std::endl;
(gdb) p s.c_str ()
$3 = 0x804b244 "Hello"
(gdb) p *s.c_str ()
$4 = 72 'H'
(gdb) c
Continuing.
from A: Hello

Program exited normally.
(gdb)
Run Code Online (Sandbox Code Playgroud)

iai*_*ain 5

A 直到完整语句执行后才会被删除。

您遇到的问题不是由 A 被删除并打印未初始化的数据引起的,而是由 r 值引用引起的。匿名实例只能通过值或 const 引用传递。

这意味着您的类将支持operator <<定义为成员函数,但不支持定义为全局函数。

为了展示这个尝试

struct A {
    f()
};

void g(A & a) {
}

void foo() {
    A a;
    a.f();
    g(a);

    A().f();
    g(A());  // This does not compile
}
Run Code Online (Sandbox Code Playgroud)

我实现了一个类似于您的 A 类的日志记录机制。它在 Visual Studio 6 中工作得很好,但在 Visual Studio 2005 中却不行。我通过使用委托而不是继承来修复它。

class A
{
    ostringstream mystream;
public:
  A () {}
  virtual ~A ()
  {    
    cout << "from A: " << mystream.str(); << std::endl;
  }
  ostream & stream()
  {
       return mystream;
  }
};

int
main ()
{
  string s = "Hello";
  A os;

  os.stream() << s;    
  A().stream() << "checking this";
}
Run Code Online (Sandbox Code Playgroud)

我假设您计划将其与日志记录和可能的宏一起使用。这就是我如何使用基于上面 A 的类。

#define TRACE_ERROR if (A::testLevel(A::Error) A(A::Error).stream()
#define TRACE_INFO if (A::testLevel(A::Info) A(A::Info).stream()
Run Code Online (Sandbox Code Playgroud)

然后在代码中

void foo()
{
    int a = ..
    std::string s = ..
    TRACE_INFO << "Some information " << a << " message: " s;
}
Run Code Online (Sandbox Code Playgroud)