비 const 참조는 어떻게 임시 객체에 바인딩 할 수 없습니까?


226

왜 임시 객체에 대한 상수가 아닌 참조를 얻을 수 getx()없습니까? 어떤 함수가 반환합니까? 분명히 이것은 C ++ Standard에서 금지되어 있지만 표준에 대한 언급아니라 그러한 제한의 목적에 관심 이 있습니다.

struct X
{
    X& ref() { return *this; }
};

X getx() { return X();}

void g(X & x) {}    

int f()
{
    const X& x = getx(); // OK
    X& x = getx(); // error
    X& x = getx().ref(); // OK
    g(getx()); //error
    g(getx().ref()); //OK
    return 0;
}
  1. C ++ 표준 에서는 객체에 대한 지속적인 참조가 금지되지 않기 때문에 객체의 수명이 원인이 될 수 없음이 분명합니다 .
  2. 상수가 아닌 함수에 대한 호출이 허용되므로 위 샘플에서 임시 개체가 일정하지 않은 것이 분명합니다. 예를 들어 ref()임시 개체를 수정할 수 있습니다.
  3. 또한 ref()컴파일러를 속이고이 임시 객체에 대한 링크를 가져 와서 문제를 해결할 수 있습니다.

게다가:

그들은 "const 참조에 임시 객체를 할당하면이 객체의 수명이 연장된다"고 말합니다. 내 추가 질문 입니다. 다음 할당은 임시 객체의 수명을 연장합니까?

X& x = getx().ref(); // OK

4
표준에 명시되어 있기 때문에 "객체의 수명이 원인이 될 수 없음"부분에 동의하지 않습니다. 임시 객체를 const 참조에 할당하면이 객체의 수명이 const 참조의 수명으로 연장됩니다. 비 const 참조에 대해서는 아무
말도

3
음, 그 원인이 "비정규 참조에 대해서는 아무 말도 없습니다 ...". 내 질문의 일부입니다. 이것에 어떤 문장이 있습니까? Standard의 저자는 비 const 참조를 잊어 버렸고 곧 다음 핵심 문제를 볼 수 있습니까?
Alexey Malistov


4
@Michael : VC는 rvalue를 상수가 아닌 참조에 바인딩합니다. 그들은 이것을 기능이라고 부르지 만 실제로는 버그입니다. (이것은 본질적으로 비논리적이기 때문에 버그가 아니라 바보 같은 오류를 방지하기 위해 명시 적으로 배제 되었기 때문에 버그가 아닙니다.)
sbi

답변:


97

rvalue 참조에 대한Visual C ++ 블로그 기사에서 :

... C ++은 실수로 임시를 수정하는 것을 원하지 않지만 수정 가능한 rvalue에서 비 const 멤버 함수를 직접 호출하는 것은 명백하므로 허용됩니다 ...

기본적으로 임시 개체가 임시 개체이므로 지금은 죽을 것이라는 이유로 임시 수정을 시도해서는 안됩니다. 비 const 메소드를 호출 할 수있는 이유는, 당신이하고있는 일을 알고 있고 그것에 대해 명시 적 인 한 (예 : reinterpret_cast 사용) "어리석은"일을 할 수 있기 때문입니다. 그러나 임시가 아닌 상수 참조에 임시를 바인딩하는 경우 완전히 잊어 버린 방법을 따라 어딘가에 객체를 조작하지 못하도록 "영원히"계속 전달할 수 있습니다.

내가 당신이라면 내 기능의 디자인을 다시 생각할 것입니다. g ()가 참조를 수락하는 이유는 무엇입니까? 그렇지 않다면 const 참조를 작성하십시오. 그렇다면, 왜 임시로 전달하려고합니까? 어쨌든 getx ()가 임시로 반환되는 이유는 무엇입니까? 실제 시나리오와 달성하려는 목표를 공유하는 경우이를 수행하는 방법에 대한 좋은 제안이있을 수 있습니다.

언어에 반대하고 컴파일러를 속이는 것은 문제를 거의 해결하지 못합니다. 일반적으로 문제를 일으 킵니다.


편집 : 의견에 대한 질문 해결 : 1) X& x = getx().ref(); // OK when will x die?-모르겠다. 나는 이것이 "언어에 반대하는 것"의 의미이기 때문에 모르겠다. 이 언어는 "임시 참조가 바인딩 참조가 아니라면 참조가 범위를 벗어날 때 죽는 경우가 아니라면, 명령문의 끝에 죽습니다"라고 말합니다. 이 규칙을 적용하면 x가 다음 명령문의 시작 부분에서 이미 죽어있는 것 같습니다. 왜냐하면 const 참조에 바인딩되지 않았기 때문입니다 (컴파일러는 ref ()가 무엇을 반환하는지 알지 못합니다). 그러나 이것은 추측 일뿐입니다.

2) 목적을 분명히 밝혔습니다. 임시를 수정할 수 없습니다 (C ++ 0x rvalue 참조는 무시). 질문은 "그러면 왜 비 const 회원에게 전화를 걸 수 있습니까?" 좋은 것이지만, 위에서 이미 언급 한 것보다 더 나은 대답은 없습니다.

3) 글 X& x = getx().ref();이 끝날 때 x가 죽는 것에 대해 옳다 면 문제는 분명합니다.

어쨌든, 귀하의 질문과 의견에 따르면이 추가 답변조차도 당신을 만족시킬 것이라고 생각하지 않습니다. 마지막 시도 / 요약은 다음과 같습니다. C ++위원회는 임시를 수정하는 것이 타당하지 않다고 결정했기 때문에 비 const 참조에 대한 바인딩을 허용하지 않았습니다. 컴파일러 구현이나 역사적인 문제가 관련되었을 수도 있습니다. 그런 다음 특정 사례가 나타 났으며 모든 확률에 대해 비 const 메소드를 호출하여 직접 수정을 허용하기로 결정했습니다. 그러나 이는 예외입니다. 일반적으로 임시를 수정할 수 없습니다. 예, C ++은 종종 그렇게 이상합니다.


2
@sbk : 1) 실제로, 올바른 문구는 "... 전체 표현 의 끝에서 ..."입니다. "완전한 표현"은 다른 표현의 하위 표현이 아닌 것으로 정의됩니다. 이것이 "문의 끝"과 항상 같은지 여부는 확실하지 않습니다.
sbi

5
@sbk : 2) 사실, 당신은 있다 우변 (임시직)를 수정하는 것을 허용했다. 내장 유형 int등 은 금지되어 있지만 사용자 정의 유형에는 허용됩니다 (std::string("A")+"B").append("C").
sbi

6
@ sbk : 3) Stroustrup이 비 값 참조에 대한 rvalue의 바인딩을 허용하지 않기 위해 (D & E에서) 이유는 Alexey가 g()객체를 수정하면 (const가 아닌 참조를 취하는 함수에서 기대할 수 있음) 죽을 객체를 수정하므로 아무도 수정 된 값을 얻을 수 없습니다. 그는 이것이 아마도 오류라고 말한다.
sbi

2
@ sbk : 당신을 화나게 한 경우 미안하지만 2) nitpicking이라고 생각하지 않습니다. Rvalue는 사용자가 만들지 않는 한 단순하지 않으며 내장되어 있지 않으면 변경할 수 있습니다. 예를 들어, 문자열 예제와 같이 내가 뭔가 잘못했는지 여부를 이해하는 데 시간이 걸렸습니다 (JFTR : 나는하지 않습니다). 그래서 나는이 구별을 심각하게 생각하는 경향이 있습니다.
sbi

5
나는 sbi에 동의합니다-이 문제는 전혀 중요 하지 않습니다 . 클래스 유형 rvalue가 비 정확성을 유지하는 것이 이동 시맨틱의 모든 기초입니다.
Johannes Schaub-litb

38

코드 getx()에서 소위 "rvalue"라는 임시 객체를 반환합니다. rvalue를 객체 (일명 변수)에 복사하거나 const 참조에 바인딩하여 참조 수명이 끝날 때까지 수명을 연장 할 수 있습니다. 비값 참조에 rvalue를 바인딩 할 수 없습니다.

이는 사용자가 표현이 끝날 때 죽을 객체를 실수로 수정하는 것을 방지하기 위해 의도적 인 디자인 결정이었습니다.

g(getx()); // g() would modify an object without anyone being able to observe

이 작업을 수행하려면 먼저 로컬 사본 또는 객체를 작성하거나 const 참조에 바인딩해야합니다.

X x1 = getx();
const X& x2 = getx(); // extend lifetime of temporary to lifetime of const reference

g(x1); // fine
g(x2); // can't bind a const reference to a non-const reference

다음 C ++ 표준에는 rvalue 참조가 포함됩니다. 따라서 참조로 알고있는 것을 "lvalue reference"라고합니다. rvalue를 rvalue 참조에 바인딩 할 수 있으며 "rvalue-ness"에 함수를 오버로드 할 수 있습니다.

void g(X&);   // #1, takes an ordinary (lvalue) reference
void g(X&&);  // #2, takes an rvalue reference

X x; 
g(x);      // calls #1
g(getx()); // calls #2
g(X());    // calls #2, too

rvalue 참조의 기본 개념은 이러한 객체가 어쨌든 죽기 때문에 해당 지식을 활용하고 특정 종류의 최적화 인 "이동 의미론"을 구현할 수 있다는 것입니다.

class X {
  X(X&& rhs)
    : pimpl( rhs.pimpl ) // steal rhs' data...
  {
    rhs.pimpl = NULL; // ...and leave it empty, but deconstructible
  }

  data* pimpl; // you would use a smart ptr, of course
};


X x(getx()); // x will steal the rvalue's data, leaving the temporary object empty

2
안녕하세요. 대단한 답변입니다. 필요 한 일을 알고는 g(getx())하지 않습니다 작업의 서명이 있기 때문에 g(X& x)그리고 get(x)우리가 할 수 없도록 바인드 임시 객체 (임시 객체를 반환 를 rvalue 아닌 일정 기준에), 맞습니까? 그리고 당신의 첫 번째 코드 조각에서, 나는 그것이 될 것이라고 생각 const X& x2 = getx();대신에 const X& x1 = getx();..
SexyBeast

1
내가 쓴 후 5 년이 지난 후에이 버그를 지적 해 주셔서 감사합니다! :-/네, 당신의 추론은 약간 뒤로 거꾸로해도 정확합니다 : 우리는 const(lvalue) 가 아닌 참조에 임시를 묶을 수 없기 때문에 getx()(에 의해)에 의해 반환 된 임시는에 get(x)대한 인수 인 lvalue 참조에 바인딩 될 수 없습니다 g().
sbi

음, 당신은 무엇을 의미 않았다 getx()(하지 get(x)) ?
SexyBeast

내가 쓸 때 "... getx을 () (와하지 (X)) ..." 나는 함수의 이름이 의미 getx(), 그리고 get(x)(당신이 쓴대로).
sbi

이 답변은 용어를 혼합합니다. rvalue는 표현식 범주입니다. 임시 객체는 객체입니다. rvalue는 임시 객체를 나타내거나 나타내지 않을 수 있습니다. 임시 객체는 rvalue로 표시되거나 표시되지 않을 수 있습니다.
MM

16

당신이 보여주는 것은 운영자 체인이 허용된다는 것입니다.

 X& x = getx().ref(); // OK

표현식은 'getx (). ref ();' 그리고 이것은 'x'에 할당되기 전에 완료됩니다.

getx ()는 참조가 아니라 완전히 형성된 객체를 로컬 컨텍스트로 반환합니다. 개체는 일시적이지만 구성 요소가 아니므로 다른 메서드를 호출하여 값을 계산하거나 다른 부작용이 발생할 수 있습니다.

// It would allow things like this.
getPipeline().procInstr(1).procInstr(2).procInstr(3);

// or more commonly
std::cout << getManiplator() << 5;

더 나은 예를 보려면이 답변의 끝 부분을보십시오.

당신은 할 수 없는 기준에 임시 결합하여 (단 정치 못한 표준이 어수선한처럼하지 않는)가 매달려 참조하여 당신을 떠날 식의 말에 파괴됩니다 개체에 대한 참조를 생성합니다 그렇게 때문에.

ref ()에 의해 반환 된 값은 유효한 참조이지만 메서드는 컨텍스트 내에서 해당 정보를 가질 수 없기 때문에 반환하는 객체의 수명에주의를 기울이지 않습니다. 기본적으로 다음과 같은 작업을 수행했습니다.

x& = const_cast<x&>(getX());

임시 객체에 대한 const 참조로 이것을 수행하는 것이 괜찮은 이유는 표준이 임시의 수명을 참조의 수명으로 연장하여 임시 객체의 수명이 명령문의 끝을 넘어 연장되기 때문입니다.

따라서 남은 유일한 질문은 왜 표준이 임시 참조를 허용하여 진술의 끝을 넘어 객체의 수명을 연장하고 싶지 않습니까?

그렇게하면 컴파일러가 임시 객체에 대해 올바른 것을 얻는 것이 매우 어려워지기 때문이라고 생각합니다. 임시 사용에 대한 const 참조를 위해 사용되었습니다. 이는 사용이 제한되어 있으므로 유용한 작업을 수행하기 위해 객체의 복사본을 만들어야하지만 일부 제한된 기능을 제공합니다.

이 상황을 생각해보십시오.

int getI() { return 5;}
int x& = getI();

x++; // Note x is an alias to a variable. What variable are you updating.

이 임시 객체의 수명을 연장하는 것은 매우 혼란 스러울 것입니다.
다음과 같은 동안 :

int const& y = getI();

사용하고 이해하기 쉬운 코드를 제공합니다.

값을 수정하려면 값을 변수로 반환해야합니다. 함수에서 객체를 다시 복사하는 비용을 피하려고하는 경우 (객체가 다시 복사 구성되어있는 것처럼 보입니다 (기술적으로)). 그런 다음 컴파일러가 '반환 값 최적화'를 매우 잘 신경 쓰지 마십시오.


3
"따라서 남은 유일한 질문은 왜 표준이 임시 말에 대한 언급이 진술의 끝을 넘어서 개체의 수명을 연장하기를 원하지 않는가하는 것입니다." 그게 다야! 당신 내 질문을 이해 합니다. 그러나 나는 당신의 의견에 동의하지 않습니다. "컴파일러를 매우 어렵게 만든다"고 말하지만 const 참조를 위해 수행되었습니다. 샘플에서 "노트 x는 변수의 별칭입니다. 어떤 변수를 업데이트하고 있습니까?" 문제 없어요. 고유 한 변수가 있습니다 (임시). 일부 임시 개체 (5와 동일)를 변경해야합니다.
Alexey Malistov

@Martin : 매달려있는 참조는 어수선한 것이 아닙니다. 나중에 메소드에서 액세스 할 때 심각한 버그가 발생할 수 있습니다!
mmmmmmmm

1
@Alexey : const 참조에 바인딩하면 임시 수명이 향상된다는 사실은 의도적으로 추가 된 예외 입니다 (수동 최적화를 허용하기 위해 TTBOMK). 비 const 참조에 대한 임시 바인딩은 프로그래머 오류 일 가능성이 높기 때문에 비 const 참조에는 예외가 추가되지 않았습니다.
sbi

1
@alexy : 보이지 않는 변수에 대한 참조! 직관이 아닙니다.
Martin York

const_cast<x&>(getX());말이 안
돼요

10

C ++ FAQ ( 굵은 글씨로 표시 )에서 논의되는 이유 :

C ++에서 비 const 참조는 lvalue에 바인딩 할 수 있고 const 참조는 lvalue 또는 rvalue에 바인딩 할 수 있지만 비 const rvalue에 바인딩 할 수있는 것은 없습니다. 그것은 사람들이 새로운 가치를 사용하기 전에 파괴되는 임시 가치를 바꾸지 못하도록 보호하는 것 입니다. 예를 들면 다음과 같습니다.

void incr(int& a) { ++a; }
int i = 0;
incr(i);    // i becomes 1
incr(0);    // error: 0 is not an lvalue

만약 그 incr (0)이 어느 누구도 보지 못했던 일시적인 값을 허용한다면, 0의 값은 1이 될 것입니다. 메모리 위치를 제외하고 값 0을 보유하십시오.


그 포트란 "제로 버그"에 의해 물린 프로그래머의 얼굴을 보는 것은 재미 있었을 것입니다! x * 0 준다 x? 뭐? 뭐??
John D

마지막 주장은 특히 약합니다. 언급 할 가치가있는 컴파일러는 실제로 0의 값을 1로 변경하거나 심지어 incr(0);그런 식으로 해석하지 않습니다 . 분명히 이것이 허용된다면, 그것은 임시 정수를 생성하고 그것을 다음으로 전달하는 것으로 해석 될 것입니다.incr()
user3204459

6

주요 문제는

g(getx()); //error

논리적 오류입니다. g결과를 수정하고 getx()있지만 수정 된 개체를 검사 할 기회가 없습니다. g매개 변수를 수정할 필요가없는 경우 lvalue 참조가 필요하지 않은 경우 값 또는 const 참조로 매개 변수를 사용할 수 있습니다.

const X& x = getx(); // OK

때로는 표현식의 결과를 재사용해야하기 때문에 유효하며 임시 객체를 다루는 것이 분명합니다.

그러나 만드는 것은 불가능합니다

X& x = getx(); // error

하지 않고 유효한 g(getx())언어 디자이너가 처음부터 피하려고했는지, 이는 유효합니다.

g(getx().ref()); //OK

메소드는의 const 만 알기 때문에 유효 this합니다. lvalue 또는 rvalue에서 호출되는지 여부는 알 수 없습니다.

C ++에서 항상 그렇듯이이 규칙에 대한 해결 방법이 있지만 명시 적으로 수행하여 수행중인 작업을 알고 있음을 컴파일러에 알리십시오.

g(const_cast<x&>(getX()));

5

이것이 허용되지 않는 이유에 대한 원래의 질문처럼 보입니다 . "대부분의 오류이기 때문에"명확하게 대답되었습니다.

FWIW, 나는 그것이 좋은 기술이라고 생각하지 않지만 어떻게 할 수 있는지 보여줄 것이라고 생각했습니다.

때로는 비 const 참조를 사용하는 메소드에 임시를 전달하려는 이유는 호출 메소드가 신경 쓰지 않는 참조에 의해 리턴 된 값을 의도적으로 버리는 것입니다. 이 같은:

// Assuming: void Person::GetNameAndAddr(std::string &name, std::string &addr);
string name;
person.GetNameAndAddr(name, string()); // don't care about addr

이전 답변에서 설명한 것처럼 컴파일되지 않습니다. 그러나 이것은 내 컴파일러로 컴파일하고 올바르게 작동합니다.

person.GetNameAndAddr(name,
    const_cast<string &>(static_cast<const string &>(string())));

이것은 캐스팅을 사용하여 컴파일러에 거짓말 할 수 있음을 보여줍니다. 분명히 사용되지 않는 자동 변수를 선언하고 전달하는 것이 훨씬 깨끗합니다.

string name;
string unused;
person.GetNameAndAddr(name, unused); // don't care about addr

이 기술은 불필요한 지역 변수를 메소드의 범위에 도입합니다. 어떤 이유로 혼동이나 오류를 피하기 위해 메소드에서 나중에 사용되지 못하게하려면 로컬 블록에 숨길 수 있습니다.

string name;
{
    string unused;
    person.GetNameAndAddr(name, unused); // don't care about addr
}

-크리스


4

왜 원하는가 X& x = getx();? X x = getx();RVO를 사용 하고 의존하십시오.


3
나는 전화를 걸 렸기 때문에 g(getx())가 아니라g(getx().ref())
알렉세이 Malistov

4
@Alexey, 그건 진짜 이유가 아닙니다. 그렇게 g하면 더 이상 손을 넣을 수없는 것을 수정 하기 때문에 논리적 인 오류 가 있습니다.
Johannes Schaub-litb

3
@ JohannesSchaub-litb 그는 신경 쓰지 않을 것입니다.
curiousguy

" RVO에 의존 하지 않는 한"RVO 에 의존 "
curiousguy

2
@ curiousguy : 그것은 매우 받아 들여진 용어입니다. "RVO"라고 언급하는 것은 전혀 잘못된 것이 아닙니다.
강아지

4

사소한 해결 방법에는 'mutable'키워드가 포함됩니다. 실제로 악한 것은 독자의 연습으로 남아 있습니다. 또는 여기를 참조하십시오 : http://www.ddj.com/cpp/184403758


3

훌륭한 질문이며 여기에 더 간결한 답변을 시도합니다 (많은 유용한 정보가 주석에 있고 소음을 찾기가 어렵 기 때문에).

일시적으로 직접 구속 되는 참조 는 수명을 연장시킨다 [12.2.5]. 반면에, 참조는 것이다 또 다른 참조하여 초기화 하지 (궁극적으로 동일한 임시 경우에도). 그것은 말이됩니다 (컴파일러는 그 참조가 궁극적으로 무엇을 참조하는지 모릅니다).

그러나이 전체 아이디어는 매우 혼란 스럽다. 예를 들어 참조 const X &x = X();만큼 오래 지속될 수 x있지만 실제로 const X &x = X().ref();는 무엇이 ref()반환 되는지 알 수 없습니다 . 후자의 경우에 대한 소멸자 X가이 행의 끝에서 호출됩니다. (이것은 사소한 소멸자가 관찰 할 수 있습니다.)

따라서 일반적으로 혼란스럽고 위험한 것처럼 보이지만 (객체 수명에 대한 규칙을 복잡하게 만드는 이유는 무엇입니까?) 최소한 const 참조가 필요하기 때문에 표준에서 이러한 동작을 설정합니다.

[ sbi 의견에서] : const 참조에 바인딩하면 임시 수명이 향상된다는 사실은 의도적으로 추가 된 예외입니다 (수동 최적화를 허용하기 위해 TTBOMK). 비 const 참조에 대한 임시 바인딩은 프로그래머 오류 일 가능성이 높기 때문에 비 const 참조에는 예외가 추가되지 않았습니다.

모든 임시 표현식은 전체 표현이 끝날 때까지 지속됩니다. 그러나 그것들을 사용하려면와 같은 트릭이 필요합니다 ref(). 합법입니다. 프로그래머에게 비정상적인 일이 일어나고 있음을 상기시키는 것 (즉, 수정이 빨리 손실되는 참조 매개 변수)을 상기시키는 것 외에는 여분의 후프가 뛰어 넘을만한 타당한 이유가없는 것 같습니다.

[또 다른 sbi 코멘트] Stroustrup이 비값 참조에 대한 rvalue의 바인딩을 허용하지 않기 위해 D & E에서 제공하는 이유는 Alexey의 g ()가 객체를 수정하면 (비 const를 취하는 함수에서 기대할 수 있기 때문입니다) 참조), 죽을 객체를 수정하므로 아무도 수정 된 값을 얻을 수 없습니다. 그는 이것이 아마도 오류라고 말한다.


2

"일관되지 않은 함수에 대한 호출이 허용되기 때문에 위의 샘플에서 임시 개체가 일정하지 않다는 것이 분명합니다. 예를 들어 ref ()는 임시 개체를 수정할 수 있습니다."

예제에서 getX ()는 const X를 반환하지 않으므로 X (). ref ()를 호출 할 때와 같은 방식으로 ref ()를 호출 할 수 있습니다. 비 const 참조를 반환하므로 const가 아닌 메소드를 호출 할 수 있습니다. 할 수없는 것은 참조를 비 const 참조에 할당하는 것입니다.

SadSidos 의견과 함께 이것은 당신의 세 가지 점을 잘못합니다.


1

Alexey가 요구하는 것을 할 수있는 곳을 공유하고 싶은 시나리오가 있습니다. Maya C ++ 플러그인에서 노드 속성으로 값을 얻으려면 다음 shenanigan을 수행해야합니다.

MFnDoubleArrayData myArrayData;
MObject myArrayObj = myArrayData.create(myArray);   
MPlug myPlug = myNode.findPlug(attributeName);
myPlug.setValue(myArrayObj);

이것은 지루하기 때문에 다음 도우미 함수를 작성했습니다.

MPlug operator | (MFnDependencyNode& node, MObject& attribute){
    MStatus status;
    MPlug returnValue = node.findPlug(attribute, &status);
    return returnValue;
}

void operator << (MPlug& plug, MDoubleArray& doubleArray){
    MStatus status;
    MFnDoubleArrayData doubleArrayData;
    MObject doubleArrayObject = doubleArrayData.create(doubleArray, &status);
    status = plug.setValue(doubleArrayObject);
}

이제 게시물 시작 부분에서 다음과 같이 코드를 작성할 수 있습니다.

(myNode | attributeName) << myArray;

문제는 Visual C ++ 외부에서 컴파일되지 않는다는 것입니다. 왜냐하면 | << 연산자의 MPlug 참조에 대한 연산자입니다. 이 코드는 여러 번 호출되므로 MPlug가 너무 많이 복사되지 않기 때문에 참조로 사용하고 싶습니다. 두 번째 함수가 끝날 때까지 임시 객체 만 있으면됩니다.

글쎄, 이것은 나의 시나리오이다. Alexey가 묘사 한 것을하고 싶은 예를 보여 줄 것이라고 생각했습니다. 모든 비평과 제안을 환영합니다!

감사.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.