2013-10-20 8 views
2

아래의 동작에 대한 표준에 대한 설명이 있습니까?C++ Ostringstream의 이상한 동작

다음 코드 :

#include <sstream> 
#include <iostream> 

using namespace std; 

int main() 
{ 
    ostringstream os1; 
    ostringstream os2; 

    os1 << 1 << " " << 2; 
    os2 << 1 << " " << 2 << " " << 3; 

    const char *p = os1.str().c_str(); 

    cout << os2.str() << endl; 
    cout << p << endl; 

    return 0; 
} 

디스플레이 출력 : 그러나

1 2 3 
1 2 3 

, 나는 디스플레이에 기대 : OS1 객체가 어떻게 든 영향을 같은

1 2 3 
1 2 

같습니다 os2.str() 호출을 제거하면 os2에 의해 예제가 올바르게 작동합니다.

Solaris Studio 12.2 및 G ++ 4.8.1 및 둘 모두가 동일한 방식으로 동작하는 경우 예제를 시도했습니다.

도움 주셔서 감사합니다.

+0

이 코드는 "1 2 3 \ n1 2 \ n"을 내 컴퓨터의 w/g ++에 인쇄합니다. – jma127

+0

여기에서 시도하십시오 : http://www.compileonline.com/compile_cpp_online.ph –

+0

@ jma127 P.An과 같은 데비안에서 g ++ 4.8.1을 사용하여 이상한 결과를 얻었습니다. – PhillipD

답변

3
const char *p = os1.str().c_str(); 

위의 줄에 문제가 있습니다.

os1.str()은 내부 문자열 버퍼를 복사하여 임시 문자열 개체를 반환합니다. 그리고 임시 객체 중 .c_str()을 가져오고 전체 표현식의 끝에서 파기됩니다. 그 결과는 을 사용하여 인쇄 할 때 파괴 된 개체를 가리키는 p을 가리 킵니다.

즉, 프로그램에서 정의되지 않은 동작 (UB)을 호출합니다.

이 시도 :

auto s = os1.str(); 
const char *p = s.c_str(); //s is not a temporary object anymore! 

를 이제 correct output을 제공합니다 (이것은 당신이 당신의 컴퓨터에 관찰 your code — 다행히도 coliru이 동일한 출력을 제공입니다이 출력이 이하지만 보장되지 것을 참고. 코드가 UB를 호출하기 때문입니다.).

+0

도움을 주셔서 감사합니다. –

2

나는 문제가 c_str()에 의해 반환 된 포인터를 유지하는 것과 관련이 있다고 생각합니다.

ostringstream::str()은 임시 문자열 개체를 반환하며 내부에 char 배열의 포인터를 저장하고 있습니다. 그러나 일단 해당 라인이 실행되면 반환 된 문자열 객체는 삭제됩니다. 그래서 귀하의 포인터가 유효하지 않습니다.

당신이 어떤 이유로 c_str 포인터 주위를 유지하려면, 당신은 또한 문자열의 사본을 보관해야합니다 :

string s = os1.str(); 
const char *p = s.c_str(); 

cout << os2.str() << endl; 
cout << p << endl; 
+1

다음과 같이 코드를 변경하면 참조를 유지하는 것처럼 보입니다. 올바르게 표시됩니다. const std :: string & s = os1.str(); const char * p = s.c_str(); –

0

는이 질문에 대한 답은 여기에 있습니다 : stringstream, string, and char* conversion confusion

stringstream.str()은 전체 표현식의 끝에서 삭제 된 임시 문자열 객체를 반환합니다. (stringstream.str(). c_str())에서 C 문자열에 대한 포인터를 얻으면 명령문이 끝나는 곳에서 삭제되는 문자열을 가리 킵니다.