2011-12-30 21 views
6

Nếu bạn cần viết lại mã C++ sau trong D, bạn sẽ làm như thế nào?Làm thế nào để viết lại mã C++ sử dụng mutable trong D?

struct A{ 

    const S* _s; 
    B _b; 
    C _c; 
    mutable C _c1, _c2; 

    A(const B& b, const C& c, const S* s){ /*...*/ } 

    void compute(const R& r) const 
    { 
     //... 
     _c1 = ... 
     _c2 = ... 
    } 
}; 

D không có mutable, và dựa trên kinh nghiệm của tôi, nó hiếm khi được sử dụng trong C++. Tuy nhiên, giả sử mutable được sử dụng vì những lý do chính đáng tại đây, các tùy chọn của tôi trong D là gì?

+0

Đây là một câu hỏi tương tự: http://stackoverflow.com/questions/4219600/logical-const-in-d –

Trả lời

3

Bạn có ba tùy chọn để đối phó với điều này:

  1. Bỏ qua số const. Điều này sẽ shit trình biên dịch lên, nhưng không có đảm bảo rằng mã của bạn sẽ làm việc như dự định. Đặc biệt, nếu bạn gọi hàm đó trên cùng một đối tượng từ nhiều luồng thì bạn đang ở lòng thương xót của các cuộc đua dữ liệu.

  2. Sử dụng một cấu trúc dữ liệu bên ngoài để lưu trữ các đối tượng có thể thay đổi:

    struct A 
    { 
        static C[const(A)*] _c1s, _c2s; 
    
        void compute(ref const(R) r) const 
        { 
         _c1s[&this] = ... 
         _c2s[&this] = ... 
        } 
    } 
    

    Tôi đang sử dụng &this là chìa khóa để các bảng băm bên ngoài, nhưng bạn có lẽ sẽ tốt hơn bằng cách sử dụng một số loại ID duy nhất . Đây là một giải pháp rất xấu xí và phức tạp. Tôi không thích nó. Ngoài ra, lưu ý rằng các bảng băm là thread-local, do đó, cùng một đối tượng sẽ có các giá trị khác nhau trên các luồng khác nhau. Điều này có thể hoặc có thể không được mong muốn cho ứng dụng cụ thể của bạn.

  3. suy nghĩ lại cách bạn sử dụng const trong D.

    Trong D, const là bắc cầu và Bitwise ví dụ: const logic không được hỗ trợ. Mục đích của việc này là để đảm bảo chống lại dữ liệu được chia sẻ đồng thời. Mặc dù mã của bạn có thể là một cách hợp lý const chính xác, nó vẫn sẽ bị hỏng nếu hai luồng cố gắng gọi compute trên cùng một đối tượng, vì vậy D không cho phép và không thoát khỏi hợp pháp (không mutable).

    Về cơ bản, bạn chỉ nên đánh dấu các hàm là const khi chúng là bitwise const.

    Kết quả của việc này là bạn nên sử dụng const ít hơn rất nhiều trong D so với bạn sẽ có trong C++ vì bạn yêu cầu bitwise const ít hơn rất nhiều so với bạn yêu cầu const hợp lý.

    Như một ví dụ, hãy xem xét một đơn giản (vô nghĩa) generic equal chức năng cho bạn biết nếu hai đối tượng đều bình đẳng:

    bool equal(T)(T lhs, T rhs) { return lhs == rhs; } 
    

    Chú ý rằng tôi đã không được đánh dấu các thông số chức năng như const. Đây là mục đích. Thử nghiệm cho sự bình đẳng không nên yêu cầu bitwise const - nó chỉ yêu cầu const hợp lý, do đó việc thực thi mức độ const của D trên các đối tượng sẽ không cần thiết hạn chế.

    Như jA_cOp nói, cộng đồng D không thấy chỗ cho const hợp lý trong D, để tốt hơn hoặc tệ hơn. Vấn đề phát sinh khi bạn cố gắng sử dụng const của D giống như const của C++. Chúng không giống nhau, vì vậy đừng sử dụng chúng theo cùng một cách! Nếu có bất kỳ khả năng nào cả một hàm có thể yêu cầu sử dụng const hợp lý thì không đánh dấu chúng là bit const!

+0

tương tự như 'bằng()' của bạn, tôi đã thực hiện hầu hết các tham số hàm 'const' và tôi chưa gặp bất kỳ vấn đề nào với nó. Đây có phải là vì 'const' vẫn bị hỏng? – Arlen

+0

Tôi nghĩ rằng const chủ yếu là làm việc ngay bây giờ. Một số điều trong Phobos không const đúng mặc dù (tôi nghĩ) và có một vấn đề lớn với các nhà thầu blit bài, nhưng tôi nghĩ rằng phần lớn các const đang làm việc. –

+0

Vì vậy, thay vì có sự tự do lớn hơn khi thêm const (trong C++), trong D thì ngược lại; nó là hạn chế hơn để làm cho các thông số const? –

6

D's immutable là chuyển tiếp, khi được cung cấp một tham chiếu không thay đổi (chẳng hạn như tham chiếu this trong hàm thành viên không thay đổi), tất cả các trường đều không thay đổi. Không có cách nào xung quanh điều này trong D. const chỉ tồn tại trong D để ràng buộc dữ liệu có thể thay đổi và bất biến, nhưng vì không thay đổi được chuyển đổi hoàn toàn thành const, nó cũng phải chuyển đổi. Một khi bạn đi bất biến (hoặc const), bạn không thể quay trở lại.

Lợi ích là một số: dữ liệu bất biến có thể được chia sẻ qua các chủ đề một cách an toàn, có thể được đưa vào ROM nếu muốn và dễ dàng giải thích.

Chỉ đơn giản là không có chỗ cho const hợp lý trong D, cho tốt hơn hoặc tồi tệ hơn.

+0

vì vậy bạn đang đề xuất mà tôi làm '_c1', '_c2',' compute () 'và tất cả các tham chiếu đến' A' không const? – Arlen

+0

@Arlen, đây là lựa chọn duy nhất của bạn nếu bạn cần thay đổi đối tượng 'this' này trong phương thức của bạn. Lưu ý rằng bạn vẫn có thể thay đổi dữ liệu được lưu trữ ở nơi khác (duh), đôi khi bạn có thể tận dụng khi dự định sử dụng dữ liệu có thể thay đổi cho mục đích bộ nhớ cache. Nhưng bộ nhớ đệm bên ngoài như vậy là xấu trong trường hợp chung (bản đồ băm, vv để đi kèm với bộ nhớ đệm? Ew!) Và vẫn là một vấn đề chưa được giải quyết. –

4

Phiên bản ngắn; bạn không thể, theo thiết kế.

Phiên bản dài hơn, các nhà thiết kế của D đã kết luận (sau một số cuộc tranh luận hoành tráng) rằng lợi ích của khả năng thay đổi có thể bị ảnh hưởng bởi những nhược điểm. (Xem: Câu trả lời jA_cOp cho một số chi tiết, nhiều reaons khác được thúc đẩy bởi một mục đích để làm cho chương trình đồng thời và lập luận có ít xấu xí.)