문제

다음 코드를 사용하여 컴파일하면 g++

class A {};

void foo(A&) {}

int main()
{
  foo(A());
  return 0;
}

다음 오류 메시지가 표시됩니다.

> g++ test.cpp -o test     
test.cpp: In function ‘int main()’:
test.cpp:10: error: invalid initialization of non-const reference of type ‘A&’ from a temporary of type ‘A’
test.cpp:6: error: in passing argument 1 of ‘void foo(A&)’

약간의 반성 후, 이러한 오류는 나에게 많은 의미가 있습니다. A() 스택에 할당 가능한 위치가 아니라 일시적인 가치이므로 주소가없는 것 같습니다. 주소가 없다면 주소를 참조 할 수 없습니다. 좋아.

하지만 기다려! 다음 변환 연산자를 클래스에 추가하면 A

class A
{
public:
  operator A&() { return *this; }
};

그렇다면 모두 잘됩니다! 내 질문은 이것이 원격으로 안전한 지 여부입니다. 정확히 무엇을 하는가 this 언제를 가리 킵니다 A() 임시 가치로 구성되어 있습니까?

나는 그 사실로 인해 약간의 자신감을 얻었습니다

void foo(const A&) {}

다음에 따라 임시 값을 수락 할 수 있습니다 g++ 그리고 내가 사용한 다른 모든 컴파일러. 그만큼 const 키워드는 항상 캐스트 될 수 있으므로 A 사이에 실제 의미 적 차이가 있으면 놀랄 것입니다. const A& 매개 변수와 an A& 매개 변수. 그래서 나는 그것이 내 질문을하는 또 다른 방법이라고 생각합니다. 왜 const 컴파일러가 안전한 것으로 간주되는 임시 가치에 대한 참조는const 참조는 아니야?

도움이 되었습니까?

해결책

주소를 가져갈 수는 없다는 것은 아닙니다 (컴파일러가 항상 스택에서 깎아내는 순서를 주문할 수 있습니다. A &를 취하는 인터페이스를 사용하면 "이 매개 변수의 내용을 수정하여 기능 호출 후 읽을 수 있습니다"라고 말합니다. 당신이 그것을 일시적으로 전달하면, 함수 후에 "수정 된"것은 존재하지 않습니다. 이것은 (아마도) 프로그래밍 오류이므로 허용되지 않습니다. 예를 들어, 고려하십시오.

void plus_one(int & x) { ++x; }

int main() {
   int x = 2;
   float f = 10.0;

   plus_one(x); plus_one(f);

   cout << x << endl << f << endl;
}

이것은 컴파일되지 않지만, 임시가 불안정에 묶을 수 있다면 컴파일하지만 놀라운 결과를 얻을 수 있습니다. plus_one (f)에서 f는 임시 int로 암시 적으로 변환 될 것입니다. Plus_one은 온도를 가져 와서 그것을 증가시켜 기본 플로트 F를 그대로 유지합니다. plus_one이 돌아 왔을 때, 그것은 효과가 없었을 것입니다. 이것은 거의 확실히 프로그래머가 의도 한 것이 아닙니다.


규칙은 때때로 엉망입니다. 일반적인 예 (설명 여기), 파일을 열고 인쇄하고 닫으려고합니다. 당신은 할 수 있기를 원할 것입니다 :

ofstream("bar.t") << "flah";

그러나 연산자 <<이 참조를 사용하기 때문에 할 수는 없습니다. 옵션은 두 줄로 나누거나 ref-to-non-const를 반환하는 메소드를 호출합니다.

ofstream("bar.t").flush() << "flah";

다른 팁

R- 값을 Const 참조에 할당하면 참조가 파괴 될 때까지 임시가 파괴되지 않음을 보장합니다. 정점이 아닌 참조에 할당하면 그러한 보증이 없습니다.

int main()
{
   const A& a2= A(); // this is fine, and the temporary will last until the end of the current scope.
   A& a1 = A(); // You can't do this.
}

당신은 willy nilly를 안전하게 캐스트 할 수 없으며 일이 효과가있을 것으로 기대합니다. Const 및 Nonst 참조에는 다른 의미론이 있습니다.

일부 사람들이 들어갈 수있는 gotcha : MSVC 컴파일러 (Visual Studio Compiler, Visual Studio 2008로 확인) ~ 할 것이다 이 코드를 문제없이 컴파일하십시오. 우리는 일반적으로 하나의 인수 (소화 할 데이터 덩어리)를 취한 기능을 위해이 패러다임을 사용하고 있었지만 때로는 청크를 검색하고 발신자에게 다시 결과를 얻기를 원했습니다. 다른 모드는 세 가지 인수를 받아 활성화되었습니다. 두 번째 인수는 검색 할 정보 (빈 문자열에 대한 기본 참조)이며 세 번째 인수는 반환 데이터 (원하는 유형의 빈 목록에 대한 기본 참조)에 대한 것이 었습니다.

이 패러다임은 Visual Studio 2005와 2008에서 작동했으며, 우리는 G ++로 컴파일하기 위해 소유 한 소유자 대신 목록이 구축되고 반환되도록 리팩터링해야했습니다.

컴파일러 스위치를 MSVC에서 이런 종류의 동작을 허용하지 않도록 설정하거나 G ++에서 허용하는 방법이 있다면 알게되어 기쁩니다. G ++ 컴파일러의 MSVC 컴파일러 / 제한성의 허용 성은 포팅 코드에 합병증을 추가합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top