2013-08-18 19 views
2

는 I이 클래스 우연히 :이 연산자 [] 오버로딩은 어떻게 작동합니까?

클래스 배열과 X, Y, Z 값에 접근하도록 [] 사용
class Vec3f 
{ 
    ... 
    float x, y, z; 
    ... 
}; 

inline float operator[](const int index) const 
{ 
    return (&x)[index]; 
} 

inline float& operator[](const int index) 
{ 
    return (&x)[index]; 
} 

그 V [0] X의 값이, V의 [그래서 1]은 y의 값이고, v [2]는 z의 값이지만,

  • return 문은 어떻게 작동합니까?
  • "x 주소에서 시작하는 인덱스로 지정된 주소에서 값 가져 오기"와 같이 읽는 것이 맞습니까?
  • Do (& x)는 괄호 안에 있어야하며, 그렇지 않으면 x [index]의 주소 ​​값을 반환합니다. 그렇지 않습니까?
+0

가이 코드는 방법에 의존 특정 컴파일러가 작동합니다. 기술적으로 이것은 유효한 코드가 아닙니다. –

답변

4

은 기술적으로이 유효한 코드가 아닙니다.

그러나 무슨 일이 일어나고 있는지 : 코드에서

// Declare four variables 
// That are presumably placed in memory one after the other. 
float x, y, z; 

:

return (&x)[index]; 

// Here we take the address of x (thus we have a pointer to float). 
// The operator [] when applied to fundamental types is equivalent to 
// *(pointer + index) 

// So the above code is 
return *(&x + index); 
// This takes the address of x. Moves index floating point numbers further 
// into the address space (which is illegal). 
// Then returns a `lvalue referring to the object at that location` 
// If this aligns with x/y/z (it is possible but not guaranteed by the standard) 
// we have an `lvalue` referring to one of these objects. 

쉬운이 일을하고 합법적하기 :

class Vec3f 
{ 
    float data[3]; 
    float& x; 
    float& y; 
    float& z; 

    public: 
     float& operator[](const int index) {return data[index];} 

     Vec3f() 
      : x(data[0]) 
      , y(data[1]) 
      , z(data[2]) 
     {} 
     Vec3f(Vec3f const& copy) 
      : x(data[0]) 
      , y(data[1]) 
      , z(data[2]) 
     { 
      x = copy.x; 
      y = copy.y; 
      z = copy.z; 
     } 
     Vec3f& operator=(Vec3f const& rhs) 
     { 
      x = rhs.x; 
      y = rhs.y; 
      z = rhs.z; 
      return *this; 
     } 
}; 
+3

글쎄요, 그건 합법적 인 것입니다. * 정확하지 않습니다. (즉, 항상 올바른 것은 아닙니다.) – greyfade

+0

그렇습니다.이 코드를 알기위한 더 깊은 연구는 필자의 기능을 보장하기 위해 패딩에 크게 의존합니다. 그리고 네, 컴파일러는 특정 수 있습니다,하지만 VS # 및 GCC에서 #/Pragma 팩 (밀어 넣기, 1) 및 # pragma 팩 (팝)없이 그것을 테스트하고 그것을 효과. 주로 C#에서 programm를 수행하므로 연산자 오버로딩에 대한 재교육이 필요했습니다. 나는 완전을 기하기 위해 다른 대답을 기다릴 것이지만 나는 당신의 것에 동의한다. –

+0

나는 클래스가 가상 메소드를 포함하지 않는 경우에만 (스 니펫은 그것을 보여주지 않지만, 그 클래스에는 가상 메소드가 없다)/legal/인 것 같다. –

관련 문제