C ++에서 임시 수명 보장?
C ++는 함수 호출 내에서 생성되었지만 매개 변수로 사용되지 않는 임시 변수의 수명을 보장합니까? 다음은 클래스의 예입니다.
class StringBuffer
{
public:
StringBuffer(std::string & str) : m_str(str)
{
m_buffer.push_back(0);
}
~StringBuffer()
{
m_str = &m_buffer[0];
}
char * Size(int maxlength)
{
m_buffer.resize(maxlength + 1, 0);
return &m_buffer[0];
}
private:
std::string & m_str;
std::vector<char> m_buffer;
};
사용 방법은 다음과 같습니다.
// this is from a crusty old API that can't be changed
void GetString(char * str, int maxlength);
std::string mystring;
GetString(StringBuffer(mystring).Size(MAXLEN), MAXLEN);
임시 StringBuffer 객체의 소멸자는 언제 호출됩니까? 그것은 :
- GetString을 호출하기 전에?
- GetString이 반환 된 후?
- 컴파일러 의존성?
C ++는 로컬 임시 변수에 대한 참조가있는 한 유효하다는 것을 보장한다는 것을 알고 있습니다. 멤버 변수에 대한 참조가있을 때 부모 개체에 적용됩니까?
감사.
그런 종류의 임시에 대한 소멸자는 full-expression의 끝에서 호출됩니다. 그것은 다른 표현의 일부가 아닌 가장 외적인 표현입니다. 그것은 함수가 반환되고 값이 평가 된 후의 경우입니다. 따라서 모두 잘 작동합니다.
사실 식 템플릿이 작동하게 만드는 이유는 다음과 같습니다.
e = a + b * c / d
모든 일시적인 것이 표현 될 때까지 지속되기 때문에
x = y
완전히 평가됩니다. 12.2 Temporary objects
표준 에 아주 간결하게 설명되어 있습니다.
litb의 대답은 정확합니다. 임시 객체 (rvalue라고도 함)의 수명은 표현식에 연결되어 있으며 임시 객체의 소멸자는 전체 표현식의 끝에서 호출되며 StringBuffer의 소멸자가 호출 될 때 m_buffer의 소멸자는 다음과 같습니다. 호출되었지만 참조이기 때문에 m_str의 소멸자는 아닙니다.
C ++ 0x는 rvalue 참조를 추가하고 의미 체계를 이동하기 때문에 약간만 변경됩니다. 본질적으로 rvalue 참조 매개 변수 (&&로 표시됨)를 사용하여 rvalue를 함수로 '이동'할 수 있으며 (복사하는 대신) rvalue의 수명은 표현식이 아닌 이동하는 객체에 바인딩 될 수 있습니다. 이에 대해 자세히 설명하는 MSVC 팀 의 정말 좋은 블로그 게시물이 있습니다.
rvalue의 이동에 대한 교육적 예제는 임시 문자열이며 생성자에서 할당을 보여 드리겠습니다. 문자열 멤버 변수를 포함하는 MyType 클래스가있는 경우 다음과 같이 생성자에서 rvalue로 초기화 할 수 있습니다.
class MyType{
const std::string m_name;
public:
MyType(const std::string&& name):m_name(name){};
}
임시 객체로이 클래스의 인스턴스를 선언 할 때 유용합니다.
void foo(){
MyType instance("hello");
}
what happens is that we avoid copying and destroying the temporary object and "hello" is placed directly inside the owning class instance's member variable. If the object is heavier weight than a 'string' then the extra copy and destructor call can be significant.
After the call to GetString returns.
I wrote almost exactly the same class:
template <class C>
class _StringBuffer
{
typename std::basic_string<C> &m_str;
typename std::vector<C> m_buffer;
public:
_StringBuffer(std::basic_string<C> &str, size_t nSize)
: m_str(str), m_buffer(nSize + 1) { get()[nSize] = (C)0; }
~_StringBuffer()
{ commit(); }
C *get()
{ return &(m_buffer[0]); }
operator C *()
{ return get(); }
void commit()
{
if (m_buffer.size() != 0)
{
size_t l = std::char_traits<C>::length(get());
m_str.assign(get(), l);
m_buffer.resize(0);
}
}
void abort()
{ m_buffer.resize(0); }
};
template <class C>
inline _StringBuffer<C> StringBuffer(typename std::basic_string<C> &str, size_t nSize)
{ return _StringBuffer<C>(str, nSize); }
Prior to the standard each compiler did it differently. I believe the old Annotated Reference Manual for C++ specified that temporaries should clean up at the end of the scope, so some compilers did that. As late as 2003, I found that behaviour still existed by default on Sun's Forte C++ compiler, so StringBuffer didn't work. But I'd be astonished if any current compiler was still that broken.
StringBuffer is in the scope of GetString. It should get destroyed at the end of GetString's scope (ie when it returns). Also, I don't believe that C++ will guarantees that a variable will exist as long as there is reference.
The following ought to compile:
Object* obj = new Object;
Object& ref = &(*obj);
delete obj;
참고URL : https://stackoverflow.com/questions/584824/guaranteed-lifetime-of-temporary-in-c
'Programing' 카테고리의 다른 글
키 저장소, 인증서 및 별명 이해 (0) | 2020.08.29 |
---|---|
SQL Server에서 비트 필드를 인덱싱해야합니까? (0) | 2020.08.29 |
“X11 DISPLAY 변수 없음”-무슨 의미입니까? (0) | 2020.08.29 |
C #에서 목록이 비어 있는지 확인 (0) | 2020.08.28 |
Visual Studio 디버깅 "빠른 조사"도구 및 람다 식 (0) | 2020.08.28 |