2010-03-17 2 views
3

다음 코드에서 'main()'의 마지막 줄에서 생성 된 개체는 식 끝 전에 소멸됩니다. 소멸자는 '< <'이 실행되기 전에 호출됩니다. 이게 그것이 있어야하는 방법인가요?익명 (이름이없는) 변수의 개체 수명이 C++입니다.

Hello 
from A: 0x80495f7 
from A: Hello 

이것은 GDB 로그입니다 :

#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"; 
} 

는 출력

(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) 

답변

2

가 나는 당신이보고있는 행동 때문에 규칙이라고 생각 익명 임시직 수없는 "그 비 const 레퍼런스 (non-const references) "로 전달 될 수 있습니다."(실제로는 아니지만 정의되지 않은 동작이나 다른 컴파일러에서의 다른 동작을 가짐). 따라서 마지막 행에서 < < 연산자로 이동하지만 위의 규칙 때문에 주로 수수료 함수 (const char *) 오버로드가 아닌 < < 연산자에 대한 멤버 (const void *) 오버로드를 찾습니다. . 따라서 임시 A가 생성되고 비 const 참조를 반환하는 < < 연산자에 전달됩니다.

따라서 연산자 < < (const void *)은 클래스의 구성원으로 정의되며 연산자 < < (const char *)은 자유 함수입니다. 함수가 임시가 아닌 임시 함수에서 호출되면 인수와 일치하는 유일한 함수가 멤버 함수에서 조회되고 자유 함수가 일치하지 않습니다. MSVC가 GCC와 다른 동작을한다는 사실을 알고 있습니다.

Infact 당신이 그 값을 볼 수 있도록 더 작은 것으로 뭔가를 검사하려고하면 (char *에서 void *로 변환하고 어떤 값을 얻을 수 있는지) 볼 수 있습니다. 사실 void * cast this "를"확인합니다. 따라서 소멸자는 맨 마지막에 호출되지만 < <은 char *를 void *로 캐스팅했으며 이는 인쇄 된 것입니다.

+0

좋은 설명, 당신은 기록했다. – iain

4

A는 전체 명령문이 실행될 때까지 삭제되지 않습니다.

당신이 가진 문제는 삭제되고 인쇄되지 않은 데이터를 인쇄하지만 r 값 참조에 의해 초래 된 문제가 아닙니다. 익명 인스턴스는 값 또는 const 참조로만 전달할 수 있습니다.

이 의미는 클래스가 멤버 함수로 정의되었지만 전역 함수로 정의되어 있지 않음을 의미합니다.

이 내가 뭔가 비주얼 스튜디오 6 괜찮 았는데 수업 A. 유사한 로깅 메커니즘을 구현하지만 비주얼 스튜디오 2005와 내가 상속 대신 위임을 사용하여 고정

struct A { 
    f() 
}; 

void g(A & a) { 
} 

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

    A().f(); 
    g(A()); // This does not compile 
} 

시도 표시합니다.

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"; 
} 

로깅과 아마도 매크로를 사용하려고한다고 가정합니다. 이것은 위의 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() 

다음 코드

void foo() 
{ 
    int a = .. 
    std::string s = .. 
    TRACE_INFO << "Some information " << a << " message: " s; 
} 
+0

감사합니다. 지금은 이해. –

관련 문제