Tôi là một nhà phát triển C nhúng gần đây đã bắt đầu rối tung với mã C++ trên thiết bị nhúng và không chắc chắn về cách áp dụng chính xác khi lớp truy cập dữ liệu dễ bay hơi như bộ nhớ -bộ đăng ký được ánh xạ hoặc dữ liệu trên thiết bị bên ngoài, chẳng hạn như Bộ chuyển đổi Analog-to-Digital (ADC).C++ Const-correctness với acess dữ liệu dễ bay hơi và bên ngoài
Ví dụ, tôi có các lớp giao diện mà các mô-đun phần cứng của thiết bị bằng cách truy cập thanh ghi bộ nhớ ánh xạ của mình thông qua một con trỏ, như vậy:
class IOPin
{
public:
/* Constructor, destructor, other methods...*/
// should this be a const method?
bool ReadIOState() {return portregs_->state;}
private:
/* Other private stuff...*/
// Constructor points this to the right set of memory-mapped registers
volatile struct portregs_t
{
uint32_t control;
uint32_t state;
uint32_t someotherreg;
} *portregs_;
};
Các tên đăng ký được tất nhiên tạo thành vì lợi ích của thí dụ. Tôi đang sử dụng một thiết bị Microchip PIC32 cho bất kỳ ai tò mò.
Từ hiểu biết có thể không chính xác của tôi, đánh dấu phương thức const
có nghĩa là trạng thái quan sát được của đối tượng không được thay đổi theo như người gọi có liên quan. Vì vậy, phương pháp ReadIOState()
không phải là const
vì nó truy cập volatile
dữ liệu có thể thay đổi bất kỳ lúc nào và do đó người gọi sẽ quan sát thay đổi? Hoặc có phải là const
vì phương pháp không thay đổi rõ ràng bất cứ điều gì?
Hiện tại, tôi đang nghiêng về phía không thực hiện phương pháp đó const
vì lý do được nêu trong câu hỏi. Điều này đặc biệt đúng sau khi vấp ngã khi this GotW article, trong đó nói rằng ý nghĩa của const
đang thay đổi để có nghĩa là "có thể đọc đồng thời". Ứng dụng nhúng của tôi là đơn luồng, nhưng tôi cho rằng đó có thể là một phép thử tốt cho số điện thoại const
nói chung.
Ngoài ra, trình biên dịch xử lý các phương pháp const
như thế nào? Đó là, những gì xảy ra khi tôi muốn thăm dò ý kiến tình trạng của IO như thế này:
// wait for IO pin to go high
while(!myIOpin.ReadIOState())
{}
Nếu ReadIOState()
là const
, sau đó có thể trình biên dịch tái sử dụng các giá trị trả về sau khi một cuộc gọi hoặc là nó đủ thông minh để thấy rằng nó đang truy cập dữ liệu volatile
và không làm điều đó?
Tôi tự hỏi liệu bạn có thể tạo ra các phương pháp dễ bay hơi giống như cách bạn có thể thực hiện các phương pháp const hay không. –
void test() volatile {} biên dịch trên VS2012 nhưng tôi không biết nó có nghĩa là gì vì tôi chưa bao giờ sử dụng dễ bay hơi trước đây. –
@NeilKirk Có, bạn có thể làm điều đó. Nó có nghĩa là hàm có thể được gọi trên một cá thể 'volatile'. Cũng giống như các hàm 'const' có thể được gọi trên các thể hiện' const'. Bạn thậm chí có thể có tất cả 4 tình trạng quá tải của một chức năng thành viên nếu bạn cảm thấy thích nó. – Angew