2009-02-13 28 views
6

Câu hỏi cuối cùng cho tối nay, tôi hứa. Những con trỏ này khiến tôi đau đầu nghiêm trọng.Làm thế nào tôi vô tình ghi đè khi tham chiếu các con trỏ này?

Tôi có một std :: danh sách <Point> gọi Polygon và một std :: danh sách các đa giác được xác định như sau:

typedef std::list<Point> Polygon; 
typedef std::list<Polygon> PolygonList; 

// List of all our polygons 
PolygonList polygonList; 

Tôi tạo ra phương pháp dưới đây để cố gắng để xóa các điểm gần nhất từ ​​một (x, y), kiểm tra tất cả các Đa giác của tôi trong polygonList của tôi.

void deleteNearestPoint(int x, int y) 
{ 
    y = screenHeight - y; 

    Polygon &closestPolygon = polygonList.front(); 
    Polygon::iterator closestPoint = closestPolygon.begin(); 

    float closestDistance = sqrt(pow(x - closestPoint->x, 2) + pow(y - closestPoint->y, 2)); 

    // Search PolygonList 
    PolygonList::iterator listIter; 
    Polygon::iterator iter; 

    for(listIter = polygonList.begin(); listIter != polygonList.end(); listIter++) 
    { 
     Polygon &tempPolygon = *listIter; 

     for(iter = tempPolygon.begin(); iter != tempPolygon.end(); iter++) 
     { 
      const float distance = sqrt(pow(x - iter->x, 2) + pow(y - iter->y, 2)); 

      if (distance < closestDistance) 
      { 
       closestPolygon = *listIter; 
       closestPoint = iter; 
       closestDistance = distance; 
      } 
     } 

    } 

    closestPolygon.erase(closestPoint); 

    redraw(); 
} 

Tuy nhiên, ở đâu đó tôi có con trỏ hoặc biến tham chiếu làm tôi say mê. Mã này biên dịch nhưng hành động theo một cách rất lạ.

Tôi đã viết một tuyên bố gỡ lỗi và cho phép nói rằng tôi có 3 đa giác trong danh sách đa giác của tôi như vậy:

Polygon #: 0
Point: (448, 43)
Point: (469 , 177)
Point: (374, 123)
Polygon #: 1
Point: (295, 360)
Point: (422, 350)
Point: (315, 266)
Point: (295, 360)
Polygon #: 2
Point: (143, 202)
Point: (301, 203)
Point: (222, 100)
Point: (143, 202)

Bây giờ, giả sử tôi thử và sử dụng chức năng xóa cho điểm x/y gần 422, 350 Kết quả mong muốn sẽ đơn giản là xóa điểm đó (422, 350) khỏi Đa giáC# 1 nhưng thay vào đó Tôi nhận được điều này:

Đa giáC#: 0
Point: (295, 360)
Point: (422, 350)
Point: (315, 266)
Point: (295, 360)
Polygon #: 1
Point: (295, 360)
Point: (315, 266)
Point: (295, 360)
Polygon #: 2
Point: (143, 202)
Point: (301, 203)
Point: (222, 100)
Điểm: (1 43, 202)

Nó đã xóa (422, 350) nhưng nó cũng có tác dụng phụ lạ khi ghi đè Polygon # 0 vào Polygon # 1 trước khi xóa điểm của nó.

Tôi biết tôi đang sử dụng con trỏ hoặc tham chiếu không chính xác trong phương pháp của mình. Ai đó có thể chỉ ra những gì tôi có thể có thể làm được là gây ra điều này? Tôi nghĩ rằng đó là vì & closestPolygon của tôi được khai báo là một tham chiếu, nhưng tôi nhận được các lỗi biên dịch nếu tôi cố gắng đặt nó thành bất kỳ thứ gì khác.

+0

Là một sang một bên, và hy vọng với một số giá trị giáo dục: làm việc với khoảng cách bình phương sẽ giúp bạn tiết kiệm chi phí sqrt() cuộc gọi. Ngoài ra, pow() khá đắt tiền; vì bạn chỉ sử dụng các số nguyên, bạn nên viết hàm square() của chính mình. – Thomas

Trả lời

4

Câu trả lời khác đã chỉ ra nguyên nhân gây ra lỗi. Như một lời khuyên chung tôi sẽ đề nghị không sử dụng tài liệu tham khảo ngoại trừ trong các đối số chức năng. Các ngữ nghĩa là khó hiểu, cũng cho một người nào đó sẽ cố gắng đọc mã của bạn. Hãy thử viết lại một cái gì đó như thế này (Tôi đã không kiểm tra mã):

void deleteNearestPoint(int x, int y) 
{ 
    y = screenHeight - y; 

    PolygonList::iterator closestPolygon = polygonList.begin(); 
    Polygon::iterator closestPoint = closestPolygon->begin(); 

    float closestDistance = sqrt(pow(x - closestPoint->x, 2) + pow(y - closestPoint->y, 2)); 

    // Search PolygonList 
    PolygonList::iterator listIter; 
    Polygon::iterator iter; 

    for(listIter = polygonList.begin(); listIter != polygonList.end(); listIter++) 
    { 
     for(iter = listIter->begin(); iter != listIter->end(); iter++) 
     { 
      const float distance = sqrt(pow(x - iter->x, 2) + pow(y - iter->y, 2)); 

      if (distance < closestDistance) 
      { 
       closestPolygon = listIter; 
       closestPoint = iter; 
       closestDistance = distance; 
      } 
     } 

    } 

    closestPolygon->erase(closestPoint); 

    redraw(); 
} 
+0

Câu trả lời hay Dani van der meer – mmcdole

+0

Có, cảm ơn. Tôi đã có một số câu trả lời hay nhưng tôi đánh giá cao bạn cho tôi thấy một số trong những điều khác bạn đã làm trong ví dụ mã này là tốt. Giống như sử dụng con trỏ của vòng lặp đầu tiên để lặp lại vòng lặp thứ hai, vv Làm việc giống như một sự quyến rũ. – KingNestor

3

Bạn không thể chỉ định cho tham chiếu.
Đây là sự khác biệt chính giữa các tham chiếu trong C++ và các tham chiếu trong C# và tương tự. Khi bạn khởi tạo biến tham chiếu với đối tượng, biến đó sẽ trở thành bí danh cho đối tượng đó. gán cho biến tham chiếu tương đương với gán cho đối tượng gốc. với điều này trong tâm trí, dòng này:

closestPolygon = *listIter; 

có nghĩa là bạn ghi đè đa giác gần nhất được tìm thấy trước đó với hình đa giác hiện tại. Điều này cũng phù hợp với kết quả bạn nhận được. Tôi đề nghị bạn sử dụng con trỏ thay vì tham chiếu cho phương pháp này.

Ngoài ra, được ghi chú bởi người khác, sử dụng pow(... , 2) là vô cùng lãng phí. tốt hơn chưa viết một cái gì đó như thế này:

x = a - b; 
xsquare = x * x; 

EDIT: Viết này với con trỏ sẽ bắt đầu với một cái gì đó như thế:

void deleteNearestPoint(int x, int y) 
{ 
    y = screenHeight - y; 

    Polygon *closestPolygon = &polygonList.front(); 
    Polygon::iterator closestPoint = closestPolygon.begin(); 
+0

Bạn có thể xây dựng một chút không? Tôi đã thử chuyển mọi thứ thành con trỏ và thất bại. – KingNestor

+0

Các pow (..., 2) là tốt, ít nhất là trong C + + đất. Nó biên dịch ra cùng một thứ vì có quá tải (float, int) và (double, int). – MSN

+0

@MSN, ngay cả như vậy, bạn có thể vẫn có phí trên của cuộc gọi hàm. – shoosh

6

Thật không may, bạn không thể rebind một tham chiếu, tức là, dòng này:

closestPolygon = * listIter;

sẽ sao chép *listIter thành closestPolygon, không được khôi phục phần giới thiệu đến *listIter.

Chỉnh sửa: Để thực hiện những gì bạn muốn, bạn nên sử dụng PolygonList::iterator thay vì Polygon & và điều chỉnh mã cho phù hợp.

2
closestPolygon = *listIter; 

thay vào đó sẽ gọi operator =() trên đối tượng được trỏ bởi tham chiếu, vì vậy nó sẽ ghi đè lên các đa giác đầu tiên với thứ hai.

Khai closestPolygon như một con trỏ để thay thế (mà có thể chỉ vào đối tượng khác nhau ngay cả sau khi tuyên bố của mình)

Polygon *closestPolygon = &(polygonList.front()); 
... 
closestPolygon = &(*listIter); 
1

tôi thấy câu hỏi của bạn đã được trả lời - Tôi sẽ ném 2 cent của tôi trong và đề nghị bạn thực hiện khoảng cách một phương pháp của Điểm để lưu mã trùng lặp.

Như những người khác đã nói bạn cũng có thể muốn có phương thức squareDistance (x, y) nếu điều đó giúp cuộc sống dễ dàng hơn cho bạn.

Hoặc có thể được gạch chân nếu bạn lo lắng về phí trên của cuộc gọi hàm.

Các vấn đề liên quan