2013-07-24 27 views
6

Tôi đã xem qua các câu hỏi phỏng vấn cho một vị trí phát triển cơ sở C++. Câu hỏi là (quote):Sửa đổi đối tượng liên tục

Mã sau đây đúng?

struct Foo 
{ 
    int i; 
    void foo (void) const 
    { 
     Foo* pointer = const_cast<Foo*>(this); 
     pointer->i = 0; 
    } 
}; 

Tôi sẽ trả lời:

Mã chính nó là hợp lệ theo quy định của C++ 03 và C++ 11 tiêu chuẩn và sẽ biên dịch thành công. Nhưng nó có thể gọi một hành vi không xác định trong khi gán con trỏ-> i = 0; nếu trường hợp của lớp mà trên đó foo() đang được gọi là khai báo là const.

Tôi có nghĩa là mã sau đây sẽ biên dịch thành công và dẫn đến hành vi không xác định.

struct Foo 
{ 
    int i; 
    Foo (void) 
    { 

    } 
    void foo (void) const 
    { 
     Foo* pointer = const_cast<Foo*>(this); 
     pointer->i = 0; 
    } 
}; 

int main (void) 
{ 
    Foo foo1; 
    foo1.foo(); // Ok 

    const Foo foo2; 
    foo2.foo(); // UB 

    return 0; 
} 

Câu trả lời của tôi có chính xác hoặc thiếu gì đó không? Cảm ơn bạn.

+11

Có, điều đó là chính xác. –

+3

"Đúng" là một từ mơ hồ. Đó là * cũng được hình thành *, có nghĩa là nó không có lỗi chẩn đoán, nhưng (như bạn nói) có thể gây ra hành vi không xác định. –

+0

IMO từ một POV thiết kế nó không phải là "đúng" vì 'const Foo foo; foo.foo(); 'không được UB. Sử dụng thành viên 'mutable' sẽ tốt hơn. – StackedCrooked

Trả lời

5

Trước tiên tôi sẽ hỏi ý nghĩa của định nghĩa mơ hồ là "chính xác". Bạn cần biết đặc điểm kỹ thuật của chương trình và hành vi dự định của nó.

Như bạn đã nói, nếu họ chỉ yêu cầu nếu nó biên dịch thì câu trả lời là 'có'. Tuy nhiên, nếu họ xác định chính xác để được an toàn để làm, sau đó bạn có thể thảo luận về các sự kiện mà bạn nêu trong câu hỏi của bạn.

Bằng cách trả lời theo cách này, người phỏng vấn có thể thấy cách bạn phân tích những gì bạn đang được hỏi, thay vì nhảy thẳng vào trả lời, theo ý kiến ​​của tôi là điều tốt để làm.

1

Mã này có thể đúng về mặt pháp lý, nhưng tôi đoán, mục đích của câu hỏi là để xác định, cho dù bạn đã hiểu khái niệm về chính const chưa. Bởi vì, ở cấp độ ngữ nghĩa, bạn có một hàm lấy một con trỏ đối tượng const ngầm định, nó sẽ đi đến sửa đổi, mà gần như chắc chắn là một lỗi. Có một số trường hợp, điều này có thể được mong muốn (vì sửa đổi là một số bộ nhớ đệm của các giá trị trả về hoặc hoạt động tương tự không thay đổi giá trị ngữ nghĩa của đối tượng), bạn sẽ sử dụng từ khóa mutable cho biến được đề cập .

+0

Cảm ơn bạn. Đây là ý tưởng tốt đẹp để đề cập đến trong câu trả lời mà tuyên bố 'i' là' mutable' sẽ sửa chữa các UB có thể đề cập. – Kolyunya

+0

Xóa * constness * là dấu hiệu lỗi trong thiết kế. Sau đó, bạn bắt đầu phân tích hậu quả của việc này. – SChepurin

0

trình xử lý gian lận sẽ chịu hậu quả.

struct Foo 
{ 
    int i; 

    Foo(int a):i(a){} 

    void foo (void) const 
    { 
     Foo* pointer = const_cast<Foo*>(this); 
     pointer->i = 0; 
    } 

    bool operator<(const Foo& rhs) const{ 
     return i<rhs.i; 
    } 
}; 

#include <map> 

int main (void) 
{ 
    std::map<Foo,int> kk; 

    for(int i=0;i<10;++i){ 
     kk.insert(std::make_pair(Foo(i),i)); 
    } 

    std::map<Foo,int>::iterator ite = kk.find(Foo(4)); 
    const Foo& foo4 = ite->first; 
    foo4.foo(); 

    ite = kk.find(Foo(4)); 
    const Foo& tmp = ite->first; // crack 

    return 0; 
} 

chương trình sẽ crack tại "const Foo & tmp = ite-> first;"

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