Từ khóa 'có thể thay đổi' có mục đích nào khác ngoài việc cho phép biến số được sửa đổi bởi hàm const không?


527

Cách đây một thời gian, tôi đã bắt gặp một số mã đánh dấu một biến thành viên của một lớp với mutabletừ khóa. Theo như tôi có thể thấy, nó chỉ đơn giản cho phép bạn sửa đổi một biến trong một constphương thức:

class Foo  
{  
private:  
    mutable bool done_;  
public:  
    void doSomething() const { ...; done_ = true; }  
};

Đây có phải là cách sử dụng duy nhất của từ khóa này hay có nhiều thứ hơn là bắt mắt? Kể từ đó, tôi đã sử dụng kỹ thuật này trong một lớp, đánh dấu một hàm boost::mutexcó thể thay đổi constđể khóa nó vì lý do an toàn luồng, nhưng thành thật mà nói, nó có cảm giác như một chút hack.


2
Một câu hỏi mặc dù, nếu bạn không sửa đổi bất cứ điều gì, tại sao bạn cần sử dụng một mutex ở nơi đầu tiên? Tôi chỉ muốn hiểu điều này.
Giải quyết sai lầm

@Misgevolution bạn đang sửa đổi một cái gì đó, bạn chỉ đang kiểm soát ai / làm thế nào có thể thực hiện sửa đổi thông qua const. Một ví dụ thực sự ngây thơ, hãy tưởng tượng nếu tôi chỉ đưa tay cầm không phải cho bạn bè, kẻ thù có được một tay cầm const. Bạn bè có thể sửa đổi, kẻ thù không thể.
iheanyi

1
Lưu ý: đây là một ví dụ tuyệt vời về việc sử dụng từ khóa mutable: stackoverflow.com/questions/15999123/ Khăn
Gabriel Staples

Tôi ước nó có thể được sử dụng để ghi đè const(các loại) vì vậy tôi không phải làm điều này : class A_mutable{}; using A = A_mutable const; mutable_t<A> a;, nếu tôi muốn const-by-default, nghĩa là mutable A a;(có thể thay đổi rõ ràng) và A a;(const const const).
alfC

Câu trả lời:


351

Nó cho phép phân biệt const const bit và const logic. Hằng logic là khi một đối tượng không thay đổi theo cách hiển thị thông qua giao diện chung, như ví dụ khóa của bạn. Một ví dụ khác sẽ là một lớp tính toán một giá trị trong lần đầu tiên nó được yêu cầu và lưu trữ kết quả.

Vì c ++ 11 mutablecó thể được sử dụng trên lambda để biểu thị rằng những thứ được ghi theo giá trị là có thể sửa đổi (chúng không có mặc định):

int x = 0;
auto f1 = [=]() mutable {x = 42;};  // OK
auto f2 = [=]()         {x = 42;};  // Error: a by-value capture cannot be modified in a non-mutable lambda

52
"Có thể thay đổi" hoàn toàn không ảnh hưởng đến hằng số logic / logic. C ++ chỉ là bit bit const và từ khóa 'có thể thay đổi' có thể được sử dụng để loại trừ các thành viên khỏi kiểm tra này. Không thể đạt được "logic" const trong C ++ ngoài việc trừu tượng hóa (ví dụ: SmartPtrs).
Richard Corden

111
@Richard: bạn đang thiếu điểm. Không có từ khóa "const const", đúng, đúng hơn, đó là một sự khác biệt về khái niệm mà lập trình viên đưa ra để quyết định thành viên nào nên được loại trừ bằng cách biến đổi, dựa trên sự hiểu biết về yếu tố cấu thành trạng thái quan sát logic của đối tượng.
Tony Delroy

6
@ajay Vâng, đó là toàn bộ điểm của markig một biến thành viên là có thể thay đổi, để cho phép nó được thay đổi trong các đối tượng const.
KeithB

6
Tại sao một người cần đột biến trên lambdas? Sẽ không đủ để nắm bắt biến bằng tham chiếu?
Giorgio

11
@Giorgio: Sự khác biệt là phần được sửa đổi xtrong lambda vẫn nằm trong lambda, tức là hàm lambda chỉ có thể sửa đổi bản sao của chính nó x. Sự thay đổi không thể nhìn thấy bên ngoài, bản gốc xvẫn không thay đổi. Hãy xem xét rằng lambdas được thực hiện như các lớp functor; các biến được bắt tương ứng với các biến thành viên.
Sebastian Mach

138

Các mutabletừ khóa là một cách để xuyên qua consttấm màn che bạn treo lên trên đối tượng của bạn. Nếu bạn có một tham chiếu const hoặc con trỏ tới một đối tượng, bạn không thể sửa đổi đối tượng đó theo bất kỳ cách nào ngoại trừ khi nào và làm thế nào nó được đánh dấu mutable.

Với consttham chiếu hoặc con trỏ của bạn, bạn bị ràng buộc để:

  • chỉ đọc quyền truy cập cho bất kỳ thành viên dữ liệu hiển thị
  • quyền chỉ gọi các phương thức được đánh dấu là const.

Các mutablengoại lệ làm cho nó vì vậy bây giờ bạn có thể viết hoặc thiết lập các thành viên dữ liệu được đánh dấu mutable. Đó là sự khác biệt duy nhất có thể nhìn thấy bên ngoài.

Bên trong những constphương thức mà bạn có thể nhìn thấy cũng có thể ghi vào các thành viên dữ liệu được đánh dấu mutable. Về cơ bản, bức màn const được xuyên thủng toàn diện. Nó hoàn toàn phụ thuộc vào người thiết kế API để đảm bảo rằng mutablenó không phá hủy constkhái niệm và chỉ được sử dụng trong các trường hợp đặc biệt hữu ích. Các mutabletừ khóa giúp bởi vì nó rõ ràng đánh dấu dữ liệu thành viên phải tuân theo những trường hợp đặc biệt.

Trong thực tế, bạn có thể sử dụng một cách constám ảnh trong toàn bộ cơ sở mã hóa của mình (về cơ bản bạn muốn "lây nhiễm" cơ sở mã hóa của mình với const"căn bệnh"). Trong thế giới này, các tham chiếu và tham chiếu constcó rất ít ngoại lệ, mang lại mã dễ hiểu và dễ hiểu hơn. Đối với một digression thú vị tìm kiếm "minh bạch tham chiếu".

Nếu không có mutabletừ khóa, cuối cùng bạn sẽ bị buộc phải sử dụng const_castđể xử lý các trường hợp đặc biệt hữu ích khác nhau mà nó cho phép (bộ nhớ đệm, đếm ref, gỡ lỗi dữ liệu, v.v.). Thật không may const_castlà có sức tàn phá đáng kể hơn mutablevì nó buộc máy khách API phá hủy sự constbảo vệ của (các) đối tượng mà anh ta đang sử dụng. Ngoài ra, nó còn gây ra sự constphá hủy trên diện rộng : const_casting một con trỏ const hoặc tham chiếu cho phép ghi và gọi phương thức truy cập vào các thành viên hữu hình. Ngược lại, mutableyêu cầu nhà thiết kế API thực hiện kiểm soát chi tiết tốt đối với các constngoại lệ và thông thường các ngoại lệ này được ẩn trong constcác phương thức hoạt động trên dữ liệu riêng tư.

(NB Tôi đã đề cập đến khả năng hiển thị dữ liệu và phương thức một vài lần. Tôi đang nói về các thành viên được đánh dấu là công khai so với riêng tư hoặc được bảo vệ, đây là một loại bảo vệ đối tượng hoàn toàn khác được thảo luận ở đây .)


8
Thêm vào đó, sử dụng const_castđể sửa đổi một phần của constđối tượng mang lại hành vi không xác định.
Brian

Tôi không đồng ý vì nó buộc ứng dụng khách API phá hủy sự bảo vệ const của các đối tượng . Nếu bạn đang sử dụng const_castđể thực hiện đột biến của các biến thành viên trong một constphương pháp, bạn sẽ không yêu cầu khách hàng đến làm các diễn viên - bạn muốn làm điều đó trong phương pháp này bởi const_casting this. Về cơ bản, nó cho phép bạn bỏ qua sự không ổn định đối với các thành viên tùy ý tại một trang web cuộc gọi cụ thể , trong khi mutablechúng ta hãy xóa const trên một thành viên cụ thể tại tất cả các trang web cuộc gọi. Cái sau thường là những gì bạn muốn cho việc sử dụng thông thường (bộ nhớ đệm, số liệu thống kê), nhưng đôi khi const_cast phù hợp với mẫu.
BeeOnRope

1
Các const_castmô hình không phù hợp tốt hơn trong một số trường hợp, chẳng hạn như khi bạn muốn tạm thời sửa đổi một thành viên, sau đó khôi phục lại nó (khá nhiều như boost::mutex). Phương thức này được xác định một cách hợp lý vì trạng thái cuối cùng giống như trạng thái ban đầu, nhưng bạn muốn thực hiện thay đổi nhất thời đó. const_castcó thể hữu ích ở đó bởi vì nó cho phép bạn loại bỏ const cụ thể trong phương pháp đó nếu bạn bị đột biến, nhưng mutablesẽ không phù hợp vì nó sẽ loại bỏ bảo vệ const khỏi tất cả các phương thức, điều này không nhất thiết phải tuân theo "làm , hoàn tác "mẫu.
BeeOnRope

2
Vị trí có thể của đối tượng được xác định const vào bộ nhớ chỉ đọc (nói chung hơn, bộ nhớ được đánh dấu chỉ đọc) và ngôn ngữ tiêu chuẩn liên quan cho phép điều này tạo ra const_castmột quả bom hẹn giờ có thể. mutablekhông có vấn đề như vậy vì các đối tượng như vậy không thể được đặt trong bộ nhớ chỉ đọc.
BeeOnRope

75

Việc bạn sử dụng với boost :: mutex chính xác là những gì từ khóa này được dành cho. Một cách sử dụng khác là để lưu trữ kết quả nội bộ để tăng tốc độ truy cập.

Về cơ bản, 'mutable' áp dụng cho bất kỳ thuộc tính lớp nào không ảnh hưởng đến trạng thái hiển thị bên ngoài của đối tượng.

Trong mã mẫu trong câu hỏi của bạn, có thể thay đổi có thể không phù hợp nếu giá trị của Done_ ảnh hưởng đến trạng thái bên ngoài, nó phụ thuộc vào những gì trong ...; phần.


35

Mutable là để đánh dấu thuộc tính cụ thể là có thể sửa đổi từ bên trong constcác phương thức. Đó là mục đích duy nhất của nó. Hãy suy nghĩ cẩn thận trước khi sử dụng nó, bởi vì mã của bạn có thể sẽ sạch hơn và dễ đọc hơn nếu bạn thay đổi thiết kế thay vì sử dụng mutable.

http://www.highprogrammer.com/alan/rant/mutable.html

Vì vậy, nếu sự điên rồ ở trên không phải là đột biến để làm gì, thì nó để làm gì? Đây là trường hợp tinh tế: mutable dành cho trường hợp một đối tượng không đổi về mặt logic, nhưng trong thực tế cần phải thay đổi. Những trường hợp này là rất ít và xa, nhưng chúng tồn tại.

Các ví dụ mà tác giả đưa ra bao gồm các bộ đệm và các biến gỡ lỗi tạm thời.


2
Tôi nghĩ rằng liên kết này đưa ra ví dụ tốt nhất về một kịch bản có thể thay đổi là hữu ích. Nó gần như xuất hiện chúng được sử dụng riêng để gỡ lỗi. (mỗi lần sử dụng đúng)
nhiệt tình

Việc sử dụng mutablecó thể làm cho mã dễ đọc và sạch hơn. Trong ví dụ sau, readcó thể constnhư mong đợi. `m_mutex có thể thay đổi; Container m_container; void add (Mục vật phẩm) {Khóa bảo vệ (m_mutex); m_container.pushback (mục); } Mục read () const {Khóa bảo vệ (m_mutex); trả về m_container.first (); } `
Th. Thielemann

Có một trường hợp sử dụng cực kỳ phổ biến: số lượng ref.
Seva Alekseyev

33

Nó hữu ích trong các tình huống mà bạn đã ẩn trạng thái nội bộ như bộ đệm. Ví dụ:

lớp HashTable
{
...
công cộng:
    tra cứu chuỗi (khóa chuỗi) const
    {
        if (key == lastKey)
            trả lại giá trị cuối cùng;

        chuỗi giá trị = lookupI Internalal (khóa);

        lastKey = key;
        lastValue = giá trị;

        giá trị trả lại;
    }

riêng tư:
    chuỗi có thể thay đổi lastKey, lastValue;
};

Và sau đó bạn có thể có một const HashTableđối tượng vẫn sử dụng lookup()phương thức của nó , nó sửa đổi bộ đệm trong.


9

mutable không tồn tại khi bạn suy luận để cho phép một người sửa đổi dữ liệu trong một hàm không đổi khác.

Mục đích là bạn có thể có một chức năng "không làm gì" với trạng thái bên trong của đối tượng và vì vậy bạn đánh dấu chức năng đó const, nhưng bạn có thể thực sự cần phải sửa đổi một số trạng thái đối tượng theo cách không ảnh hưởng đến chính xác của nó chức năng.

Từ khóa có thể hoạt động như một gợi ý cho trình biên dịch - trình biên dịch lý thuyết có thể đặt một đối tượng không đổi (chẳng hạn như toàn cục) trong bộ nhớ được đánh dấu chỉ đọc. Sự hiện diện của mutablegợi ý rằng điều này không nên được thực hiện.

Dưới đây là một số lý do hợp lệ để khai báo và sử dụng dữ liệu có thể thay đổi:

  • Chủ đề an toàn. Khai báo a mutable boost::mutexlà hoàn toàn hợp lý.
  • Số liệu thống kê. Đếm số lượng cuộc gọi đến một hàm, đưa ra một số hoặc tất cả các đối số của nó.
  • Ghi nhớ. Tính toán một số câu trả lời đắt tiền, và sau đó lưu trữ nó để tham khảo trong tương lai thay vì tính toán lại.

2
Câu trả lời tốt, ngoại trừ nhận xét về khả năng biến đổi là một "gợi ý". Điều này làm cho có vẻ như thành viên có thể thay đổi đôi khi sẽ không thể bị biến đổi nếu trình biên dịch đặt đối tượng vào ROM. Hành vi của mutable được xác định rõ.
Richard Corden

2
Ngoài việc đặt một đối tượng const trong bộ nhớ chỉ đọc, trình biên dịch cũng có thể quyết định tối ưu hóa các cuộc gọi const fucntion ra khỏi một vòng lặp, ví dụ. Một bộ đếm thống kê có thể thay đổi trong một hàm const khác vẫn sẽ cho phép tối ưu hóa như vậy (và chỉ đếm một cuộc gọi) thay vì ngăn chặn tối ưu hóa chỉ vì mục đích đếm nhiều cuộc gọi hơn.
Hagen von Eitzen

@HagenvonEitzen - Tôi khá chắc chắn rằng điều đó không chính xác. Một trình biên dịch không thể nâng các hàm ra khỏi một vòng lặp trừ khi nó có thể chứng minh rằng không có tác dụng phụ. Bằng chứng đó thường liên quan đến việc thực sự kiểm tra việc thực hiện chức năng (thường là sau khi nó được nội tuyến) và không dựa vào const(và việc kiểm tra như vậy sẽ thành công hay thất bại bất kể consthoặc mutable). Đơn giản chỉ cần khai báo hàm constlà không đủ: một consthàm không có tác dụng phụ như sửa đổi biến toàn cục hoặc một cái gì đó được truyền cho hàm, vì vậy nó không phải là một đảm bảo hữu ích cho bằng chứng đó.
BeeOnRope

Bây giờ, một số trình biên dịch có các tiện ích mở rộng đặc biệt như _ccribution __ ((const)) và __attribution __ ((thuần)), mà _do có các hiệu ứng như vậy , nhưng điều đó chỉ liên quan đến consttừ khóa trong C ++.
BeeOnRope

8

Vâng, đó là những gì nó làm. Tôi sử dụng nó cho các thành viên được sửa đổi bằng các phương thức không thay đổi logic trạng thái của một lớp - ví dụ, để tăng tốc độ tra cứu bằng cách triển khai bộ đệm:

class CIniWrapper
{
public:
   CIniWrapper(LPCTSTR szIniFile);

   // non-const: logically modifies the state of the object
   void SetValue(LPCTSTR szName, LPCTSTR szValue);

   // const: does not logically change the object
   LPCTSTR GetValue(LPCTSTR szName, LPCTSTR szDefaultValue) const;

   // ...

private:
   // cache, avoids going to disk when a named value is retrieved multiple times
   // does not logically change the public interface, so declared mutable
   // so that it can be used by the const GetValue() method
   mutable std::map<string, string> m_mapNameToValue;
};

Bây giờ, bạn phải sử dụng điều này một cách cẩn thận - các vấn đề tương tranh là một mối quan tâm lớn, vì người gọi có thể cho rằng chúng là luồng an toàn nếu chỉ sử dụng constcác phương thức. Và tất nhiên, việc sửa đổi mutabledữ liệu không nên thay đổi hành vi của đối tượng theo bất kỳ cách thức quan trọng nào, điều gì đó có thể bị vi phạm bởi ví dụ tôi đã đưa ra, ví dụ, dự kiến ​​các thay đổi được ghi vào đĩa sẽ hiển thị ngay lập tức cho ứng dụng .


6

Mutable được sử dụng khi bạn có một biến trong lớp chỉ được sử dụng trong lớp đó để báo hiệu những thứ như ví dụ là mutex hoặc lock. Biến này không thay đổi hành vi của lớp, nhưng là cần thiết để thực hiện an toàn luồng của chính lớp đó. Do đó, nếu không có "mutable", bạn sẽ không thể có các hàm "const" bởi vì biến này sẽ cần phải được thay đổi trong tất cả các hàm có sẵn cho thế giới bên ngoài. Do đó, mutable đã được giới thiệu để làm cho một biến thành viên có thể ghi được ngay cả bởi một hàm const.

Biến thể được chỉ định thông báo cho cả trình biên dịch và trình đọc rằng nó an toàn và dự kiến ​​rằng một biến thành viên có thể được sửa đổi trong hàm const thành viên.


4

mutable chủ yếu được sử dụng trên một chi tiết thực hiện của lớp. Người dùng của lớp không cần biết về nó, do đó, anh ta nghĩ rằng "nên" là const. Ví dụ của bạn về việc có một mutex có thể thay đổi là một ví dụ điển hình tốt.


4

Việc bạn sử dụng nó không phải là hack, mặc dù giống như nhiều thứ trong C ++, mutable có thể là hack cho một lập trình viên lười biếng, người không muốn quay trở lại và đánh dấu thứ gì đó không nên là không phải là const.


3

Sử dụng "có thể thay đổi" khi đối với những thứ không hợp lệ đối với người dùng (và do đó nên có các ký hiệu "const" trong API của lớp công khai) nhưng KHÔNG trạng thái trong trạng thái THỰC HIỆN cơ bản (mã trong .cpp của bạn).

Các trường hợp tôi sử dụng thường xuyên nhất là lười khởi tạo các thành viên "dữ liệu cũ" không có trạng thái. Cụ thể, đó là lý tưởng trong các trường hợp hẹp khi các thành viên như vậy tốn kém để xây dựng (bộ xử lý) hoặc mang theo (bộ nhớ) và nhiều người dùng đối tượng sẽ không bao giờ yêu cầu họ. Trong tình huống đó, bạn muốn xây dựng lười biếng ở mặt sau để thực hiện, vì 90% các đối tượng được xây dựng sẽ không bao giờ cần phải xây dựng chúng, tuy nhiên bạn vẫn cần trình bày API không trạng thái chính xác cho tiêu dùng công cộng.


2

Mutable thay đổi ý nghĩa của consttừ const bit const thành const const cho lớp.

Điều này có nghĩa là các lớp với các thành viên có thể thay đổi được dài hơn const bit và sẽ không còn xuất hiện trong các phần chỉ đọc của tệp thực thi.

Hơn nữa, nó sửa đổi kiểm tra kiểu bằng cách cho phép các consthàm thành viên thay đổi các thành viên có thể thay đổi mà không cần sử dụng const_cast.

class Logical {
    mutable int var;

public:
    Logical(): var(0) {}
    void set(int x) const { var = x; }
};

class Bitwise {
    int var;

public:
    Bitwise(): var(0) {}
    void set(int x) const {
        const_cast<Bitwise*>(this)->var = x;
    }
};

const Logical logical; // Not put in read-only.
const Bitwise bitwise; // Likely put in read-only.

int main(void)
{
    logical.set(5); // Well defined.
    bitwise.set(5); // Undefined.
}

Xem các câu trả lời khác để biết thêm chi tiết nhưng tôi muốn nhấn mạnh rằng nó không chỉ dành cho loại saftey và nó ảnh hưởng đến kết quả được biên dịch.


1

Trong một số trường hợp (như các trình vòng lặp được thiết kế kém), lớp cần giữ một số đếm hoặc một số giá trị ngẫu nhiên khác, điều đó không thực sự ảnh hưởng đến "trạng thái" chính của lớp. Đây là thường xuyên nhất mà tôi thấy mutable được sử dụng. Nếu không thể thay đổi, bạn sẽ buộc phải hy sinh toàn bộ thiết kế của mình.

Nó cảm thấy giống như một hack hầu hết thời gian đối với tôi là tốt. Hữu ích trong rất ít tình huống.


1

Ví dụ kinh điển (như đã đề cập trong các câu trả lời khác) và tình huống duy nhất tôi thấy mutabletừ khóa được sử dụng cho đến nay, là để lưu trữ kết quả của một Getphương thức phức tạp , trong đó bộ đệm được triển khai như một thành viên dữ liệu của lớp chứ không phải là một biến tĩnh trong phương thức (vì lý do chia sẻ giữa một số chức năng hoặc độ sạch đơn giản).

Nói chung, các lựa chọn thay thế cho việc sử dụng mutabletừ khóa thường là một biến tĩnh trong phương thức hoặc const_castthủ thuật.

Một lời giải thích chi tiết là ở đây .


1
Tôi chưa bao giờ nghe nói về việc sử dụng các thành viên tĩnh như một sự thay thế chung cho các thành viên có thể thay đổi. Và const_castchỉ dành cho khi bạn biết (hoặc đã được bảo đảm) rằng một cái gì đó sẽ không bị thay đổi (ví dụ như khi can thiệp vào thư viện C) hoặc khi bạn biết nó không được khai báo const. Tức là, sửa đổi một biến const const đúc kết quả trong hành vi không xác định.
Sebastian Mach

1
@phresnel Theo "biến tĩnh" Tôi có nghĩa là biến tự động tĩnh trong phương thức (nằm trong các cuộc gọi). Và const_castcó thể được sử dụng để sửa đổi một thành viên lớp trong một constphương thức, đó là những gì tôi đã đề cập đến ...
Daniel Hershcovich

1
Điều đó không rõ ràng với tôi, như bạn đã viết "nói chung" :) Liên quan đến sửa đổi thông qua const_cast, như đã nói điều này chỉ được phép khi đối tượng không được khai báo const. Ví dụ const Frob f; f.something();, với void something() const { const_cast<int&>(m_foo) = 2;kết quả trong hành vi không xác định.
Sebastian Mach

1

Biến đổi có thể có ích khi bạn ghi đè hàm const ảo và muốn sửa đổi biến thành viên lớp con trong hàm đó. Trong hầu hết các trường hợp, bạn sẽ không muốn thay đổi giao diện của lớp cơ sở, vì vậy bạn phải sử dụng biến thành viên có thể thay đổi của chính bạn.


1

Từ khóa có thể thay đổi rất hữu ích khi tạo sơ khai cho mục đích kiểm tra lớp. Bạn có thể khai thác một hàm const và vẫn có thể tăng bộ đếm (có thể thay đổi) hoặc bất kỳ chức năng kiểm tra nào bạn đã thêm vào sơ khai của mình. Điều này giữ cho giao diện của lớp còn nguyên vẹn.


0

Một trong những ví dụ tốt nhất mà chúng tôi sử dụng có thể thay đổi là, trong bản sao sâu. trong bản dựng xây dựng, chúng tôi gửi const &objnhư là đối số. Vì vậy, đối tượng mới được tạo sẽ có kiểu không đổi. Nếu chúng tôi muốn thay đổi (chủ yếu là chúng tôi sẽ không thay đổi, trong trường hợp hiếm hoi chúng tôi có thể thay đổi), các thành viên trong đối tượng const mới được tạo này, chúng tôi cần khai báo nó là mutable.

mutablelớp lưu trữ chỉ có thể được sử dụng trên thành viên dữ liệu non const không tĩnh của một lớp. Thành viên dữ liệu có thể thay đổi của một lớp có thể được sửa đổi ngay cả khi đó là một phần của đối tượng được khai báo là const.

class Test
{
public:
    Test(): x(1), y(1) {};
    mutable int x;
    int y;
};

int main()
{
    const Test object;
    object.x = 123;
    //object.y = 123;
    /* 
    * The above line if uncommented, will create compilation error.
    */   

    cout<< "X:"<< object.x << ", Y:" << object.y;
    return 0;
}

Output:-
X:123, Y:1

Trong ví dụ trên, chúng ta có thể thay đổi giá trị của biến thành viên xmặc dù đó là một phần của đối tượng được khai báo là const. Điều này là do biến xđược khai báo là có thể thay đổi. Nhưng nếu bạn cố gắng sửa đổi giá trị của biến thành viên y, trình biên dịch sẽ đưa ra lỗi.


-1

Chính từ khóa 'mutable' thực sự là một từ khóa dành riêng. Vì vậy, nó được sử dụng để thay đổi giá trị của biến không đổi. Nếu bạn muốn có nhiều giá trị của một hằng số, hãy sử dụng từ khóa có thể thay đổi.

//Prototype 
class tag_name{
                :
                :
                mutable var_name;
                :
                :
               };   
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.