2012-06-29 5 views
3

크로스 플랫폼 (win32 & 리눅스)이 될 함수를 작성하고 datetime [hh : mm : ss dd-mm-yyyy]의 문자열 표현을 반환하고 싶습니다. 난 그냥 아래 스트림 방식으로 임시로 반환 된 문자열을 사용하려는 것을 알고함수에서 문자열 반환

: 나는 다음과 같은 프로토 타입으로 함수를 작성 간주

std::cout << DateTime() << std::endl; 

const char* DateTime(); 

당신이 돌아 오면 문자 배열은 완료되면 삭제해야합니다. 그러나 나는 일시적인 것을 원한다. 나는 문자열의 할당 해제에 대해 걱정할 필요가 없다. 내가 날짜 시간에서 스택 변수의 복사본을 반환하고있어 실현

#include <ctime> 
#include <string> 
#include <sstream> 

std::string DateTime() 
{ 
    using namespace std; 

    stringstream ss; 
    string sValue; 
    time_t t = time(0); 
    struct tm * now = localtime(&t); 

    ss << now->tm_hour << ":"; 
    ss << now->tm_min << ":"; 
    ss << now->tm_sec << " "; 
    ss << now->tm_mday + 1 << " "; 
    ss << now->tm_mon + 1 << " "; 
    ss << now->tm_year + 1900; 

    sValue = ss.str(); 

    return sValue; 
} 

:

그래서 난 그냥 표준 : : 문자열을 반환하는 함수를 작성했습니다. 이것은 DateTime 스택에 문자열을 만들고, 채우고, 복사본을 반환하고 스택에서 복사본을 파괴한다는 점에서 비효율적입니다.

이 비효율적 인 문제를 해결하기 위해 C++ 11 이동 의미론 혁명이 수행되었습니다.이를 개선 할 수 있습니까?

+3

1) NRVO이 완전한 않은 문제가 있습니다. 2) 어떤 이유로 든 NRVO _didn't_가 시작되면 예가 반환 값은 복사되지 않고 이동됩니다. – ildjarn

+0

체크 아웃 : http://stackoverflow.com/a/3109981/484072 – peacemaker

+2

NRVO 란 무엇입니까 ??? – fishfood

답변

6

LAPIN, 당신의 코드가 잘 C++ (11) 코드입니다. C++ 98/03에서 코드는 이고 컴파일러 최적화로 인해이 효율적일 수는 있지만 이러한 최적화는 보장되지 않습니다. C++ 11에서는 동일한 최적화를 통해 여전히 수익을 얻을 수 있지만 그렇지 않은 경우에는 문자열이 복사되는 대신 이동됩니다.

죄책감으로 가치가 돌아갑니다! :-)

마이너 니트 :

string sValue = ss.str(); 
return sValue; 

아니면도 : 그것은 대신 블록의 상단에, 처음 사용할 때의 지점에서 값을 선언하는 가장 좋은 방법은

입니다

return ss.str(); 

그러나 이것은 단지 사소한 것입니다. 귀하의 코드는 으로 효율적입니다.

+0

몇 년 전에 너무 많은 MSSQL 저장 프로 시저를 작성했을 때 내 코드 앞에 변수를 선언하는 습관을 시작했습니다. 효율성을 위해 첫 번째 사용 시점에 vars를 선언하기 전에 귀하의 요점을 들었습니다. 나는 동의합니다. 그러나 나는 여전히 코드 앞에 선언하는 것을 발견합니다. – fishfood

-1

RVO/NRVO가없는 세계에서 이것은 사전 C++ 11 표준 라이브러리의 복사본 구성을 피해야합니다. 문자열에 대한 이동 생성자가있는 포스트 C++ 11 라이브러리에서는 여전히 호출되는 이동 생성자를 피합니다. 그것은 아마도 사소한 차이 일 테지만 여전히 OP가 더 나은 방법을 묻고있었습니다.

은 (그리고 그래 내가 문자열에서 상속 못생긴 동의하지만, 작업을 수행합니다.)

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

using namespace std; 

class DateString : public string { 

public: 
DateString() : string()  { 

    stringstream ss; 
    time_t t = time(0); 
    struct tm * now = localtime(&t); 

    ss << now->tm_hour << ":"; 
    ss << now->tm_min << ":"; 
    ss << now->tm_sec << " "; 
    ss << now->tm_mday + 1 << " "; 
    ss << now->tm_mon + 1 << " "; 
    ss << now->tm_year + 1900; 

    append(ss.str()); 

} 
}; 

int main() 
{ 
    cout << DateString() << endl; 
    return 0; 
} 
+3

1)'std :: string'에서 상속하는 것은 (도덕적으로) 잘못되었습니다. 2) OP가 이미 가지고있는 코드는 NRVO가 없어도 복사 구성을 피할 것입니다. – ildjarn

-1

좋아요,이 스레드가 안전하지 않다는 것을 알고 있습니다. 그리고 나는 아마도 지옥 끝으로 downvoted 될 것이지만, 저는 (CERN 's ROOT)를 사용하는 라이브러리에서 다음을 본 것입니다 :

const char * myfunc(){ 

    static std::string mystr; 

    /*populate mystr */ 

    return mystr.c_str(); 
} 

이것은 아무도 포인터를 잡을 정도로 바보가 아닐 경우에만 작동합니다.

이것은 무엇이든지간에 누출되지 않는 임시적인 방법입니다.

+0

예, 저는 * 당신에게 그런 일을 하달 할 것입니다. – Puppy

+0

그것은 빠른 DeadMG이었다! :-)이 대답의 문제는 정의되지 않은 동작을 호출한다는 것입니다. 클라이언트가'cout'에 포인터를 보내면, 로컬 'mystr'는 이미 그 포인터가 가리키는 문자 배열을 삭제했습니다. 그것은 작동 할 수도 있고, Simon이 게시하기 전에 테스트 한 것은 틀림 없습니다. 그러나 또한 작동하지 않을 수도 있습니다. 다중 스레드 환경에서 동일한 응용 프로그램이 작동하고 때로는 작동하지 않을 수도 있습니다. –

+3

@Howard :'mystr'은 정적입니다. 그래서 여기에는 파괴가 없습니다. 나는 DeadMG의 니트가 스레드로부터 안전하지 않다고 생각합니다. – ildjarn

5

이 작업을 수행하는 또 다른 방법은 같이 스트림 삽입과 그것을 함수 개체를 만드는 것입니다 :

struct DateTime() 
{ 
    friend std::ostream& operator<<(std::ostream& os, DateTime) 
    { 
     time_t t = time(0); 
     struct tm * now = localtime(&t); 

     os << now->tm_hour << ":"; 
     os << now->tm_min << ":"; 
     os << now->tm_sec << " "; 
     os << now->tm_mday + 1 << " "; 
     os << now->tm_mon + 1 << " "; 
     os << now->tm_year + 1900; 

     return os; 
    } 

    // Could be converted to a static method, 
    // since DateTime has no internal state 
    std::string str() const 
    { 
     // the following 3 lines can be replaced by 
     // return boost::lexical_cast<std::string>(*this); 
     std::ostringstream ss; 
     ss << *this; 
     return ss.str(); 
    } 

    operator std::string() const 
    { return str(); } 
};