2010-03-26 27 views
11

Bắt đầu từ Visual Studio 2010, lặp qua một bộ dường như trả về một trình lặp mà dereferences dữ liệu là 'const data' thay vì không const.Tham chiếu Const khi thiết lập lặp lại dereferencing trên thiết lập, bắt đầu từ Visual Studio 2010

Đoạn mã sau là ví dụ về thứ gì đó biên dịch trên Visual Studio 2005, nhưng không phải vào năm 2010 (đây là một ví dụ nhân tạo, nhưng minh họa rõ ràng vấn đề chúng tôi tìm thấy trên mã riêng của chúng tôi).

Trong ví dụ này, tôi có một lớp lưu trữ vị trí cùng với nhiệt độ. Tôi xác định toán tử so sánh (không phải tất cả chúng, chỉ đủ để minh họa vấn đề) mà chỉ sử dụng vị trí chứ không phải nhiệt độ. Vấn đề là đối với tôi hai trường hợp giống hệt nhau nếu vị trí giống hệt nhau; Tôi không quan tâm đến nhiệt độ.

#include <set> 

class DataPoint 
    { 
    public: 
     DataPoint (int x, int y) : m_x(x), m_y(y), m_temperature(0) {} 
     void setTemperature(double t) {m_temperature = t;} 
     bool operator<(const DataPoint& rhs) const 
     { 
     if (m_x==rhs.m_x) return m_y<rhs.m_y; 
     else    return m_x<rhs.m_x; 
     } 
     bool operator==(const DataPoint& rhs) const 
     { 
     if (m_x!=rhs.m_x) return false; 
     if (m_y!=rhs.m_y) return false; 
     return true; 
     } 
    private: 
     int m_x; 
     int m_y; 
     double m_temperature; 
    }; 

typedef std::set<DataPoint> DataPointCollection; 

void main(void) 
{ 
DataPointCollection points; 

points.insert (DataPoint(1,1)); 
points.insert (DataPoint(1,1)); 
points.insert (DataPoint(1,2)); 
points.insert (DataPoint(1,3)); 
points.insert (DataPoint(1,1)); 

for (DataPointCollection::iterator it=points.begin();it!=points.end();++it) 
    { 
    DataPoint &point = *it; 
    point.setTemperature(10); 
    } 
} 

Trong thói quen chính tôi có một bộ mà tôi thêm một số điểm. Để kiểm tra tính chính xác của toán tử so sánh, tôi thêm các điểm dữ liệu với cùng một vị trí nhiều lần. Khi viết nội dung của bộ, tôi có thể thấy rõ chỉ có 3 điểm trong bộ này.

Vòng lặp cho vòng lặp trên bộ và đặt nhiệt độ. Về mặt logic, điều này được cho phép, vì nhiệt độ không được sử dụng trong các toán tử so sánh.

Mã này biên dịch một cách chính xác trong Visual Studio 2005, nhưng cho lỗi biên dịch trong Visual Studio 2010 trên dòng sau (trong vòng lặp cho-):

DataPoint &point = *it; 

Các lỗi cho là nó không thể gán "const DataPoint" thành [không const] "DataPoint &".

Dường như bạn không có cách viết phong nha (= không bẩn) viết mã này trong VS2010 nếu bạn có toán tử so sánh chỉ so sánh các phần của thành viên dữ liệu.

giải pháp có thể là:

  • Thêm một const-cast vào dòng nơi nó mang lại cho một lỗi
  • Làm nhiệt độ có thể thay đổi và làm cho setTemperature một phương pháp const

Nhưng đối với tôi cả hai giải pháp có vẻ khá 'bẩn thỉu'.

Có vẻ như ủy ban tiêu chuẩn C++ đã bỏ qua tình huống này. Hay không?

Giải pháp sạch để giải quyết vấn đề này là gì? Một số người trong số các bạn gặp vấn đề tương tự này và bạn đã giải quyết nó như thế nào?

Patrick

+1

http://connect.microsoft.com/VisualStudio/feedback/details/532300/std-set-t-iterator-and-std-set-t-const-iterator-are-the- cùng loại-break-code – mlvljr

+1

Liên kết đẹp. Có vẻ tôi không phải là người duy nhất tìm thấy nó. – Patrick

+0

Yup, tôi vừa viết một số (bây giờ rõ ràng) lỗi stl :: bộ mã và sau một giờ gỡ lỗi này-và-đó đi googling, đến cả hai ở đây và có :) – mlvljr

Trả lời

13

Các iterator nên cung cấp cho bạn một tham chiếu const (và đó là những gì các tiêu chuẩn nói nó nên làm), vì việc thay đổi điều gọi sẽ phá hủy tính hợp lệ của cấu trúc dữ liệu cơ bản của bộ - tập doesn' t "biết" rằng trường bạn đang thay đổi không thực sự là một phần của khóa. Các lựa chọn thay thế là thực hiện thay đổi bằng cách xóa và thêm lại hoặc sử dụng sơ đồ std :: thay thế.

+0

Nếu tìm thấy vấn đề này trong mã được viết bởi một ex- đồng nghiệp. Cá nhân tôi sẽ sử dụng thực sự sử dụng std :: bản đồ, nhưng với tôi nó trông giống như các nhà khai thác so sánh tùy chỉnh và thiết lập không phù hợp tốt với nhau trong VS2010. – Patrick

+4

So sánh tùy chỉnh và các tập hợp chỉ hoạt động tốt nhưng các loại và bộ dữ liệu có thể thay đổi thì không. –

0

Nếu bạn không muốn xóa và thêm lại khi Neil đề xuất bạn có thể tạo setTemperatureconstm_temperaturemutable.

+0

Chỉ là những gì tôi đã nói trong câu hỏi của tôi. Mặc dù điều này làm việc, tôi vẫn không tìm thấy một giải pháp phong nha. – Patrick

0

Đặt là nghĩa vụ phải trả về trình lặp vòng lặp const bởi vì nó không biết liệu có bất kỳ hàm thành viên nào có thể thay đổi thứ tự.

Có vẻ như bạn thực sự muốn có một bản đồ, nơi bạn ánh xạ khóa bất biến (x, y) của bạn đến nhiệt độ biến đổi.

1

Vừa mới bắt đầu chuyển đổi của chúng tôi đến năm 2010 và đây là rào cản lớn nhất mà chúng tôi đang đối mặt. May mắn là họ đã tiết lộ một số vấn đề lâu dài mà chúng tôi đã thay đổi một phần của những gì tạo nên thứ tự của bộ này.

Trong các trường hợp khác, giải pháp của chúng tôi là sử dụng các phương thức có thể thay đổi và khai báo là const. Khi chuyển qua trình vòng lặp không tham chiếu tới một hàm bằng tham chiếu (hoặc con trỏ hoặc tham chiếu), thì chúng ta đã thực hiện đối số đó nếu nó không bị thay đổi.

Dennis

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