[C++] mutable và volatile trong C++

mutable

Khi lập trình với C++ chắc hẳn đôi ba lần chúng ta nghe về từ khóa mutable.

Vậy từ khóa mutable dùng để làm gì ?

Thỉnh thoảng có thế chúng ta cần thay đổi giá trị của data member thông qua hàm hằng (const function) của class. Tuy nhiên như chúng ta đã biết hàm hằng không cho phép thay đổi giá trị của data member.

=> Chúng ta phải làm thế nào ?

Trong C++ cũng cấp cho ta từ khóa mutable để dễ dàng thực hiện điều đó. Với data member được khai báo là mutable cho phép chúng ta thay đổi giá trị của chúng trong hàm hằng.

Ví dụ:

#include <iostream>

using namespace std;

class TestMubtable
{
   
   private:

      mutable int m_accessCount;
 
      bool m_flag;
 
   public:
 
      //Hàm hằng thay đối giá trị m_accessCount
      bool GetFlag() const
      {
 
         m_accessCount++;
 
         return m_flag;
 
      }

 };

int main()
{
 
   //TODO
   
   return 0;
 
}

Từ khóa mubtable cho phép ta thay đổi data member của đối tượng hằng (const object)

Ví dụ:

#include <iostream> 

using namespace std;

class TestMubtable
{
 
   public:
 
      mutable int val;
 
};

int main()
{
 
   const TestMubtable mutableObject;
 
   mutableObject.val = 20;
 
   cout << mutableObject.val << endl;
 
   return 0;
 
}

Chú ý:

  • mubtable chỉ áp dụng cho data member non-static (không phải static) và non-const (không phải là hằng số) của của class.

volatile

Optimize code

Xét ví dụ

int val = 10;
 
while (val == 10)
{
 
   //TODO
 
}

Khi biên dịch, trình biên dịch có thể sẽ optimize code.

Nếu trình biên dịch thấy biến val KHÔNG được thay đổi giá trị lần nào, khi đó trình biên dịch có thể sẽ optimize biến val.
Biến val sẽ được lưu giá trị vào thanh ghi 1 lần, và trình biên dịch chỉ lấy giá trị của biến val từ thanh ghi mà không lấy giá trị trực tiếp từ địa chỉ biến val. Khi đó vòng lặp while trở thành while (true);

Optimize code sẽ giúp chương trình chạy nhanh hơn, tuy nhiên trong nhiều trường hợp cho kết quả không mong muốn. Như ví dụ trên, nếu ta thay đổi giá trị biến val từ ngoài chương trình hoặc từ 1 thread khác để kết thúc vòng lặp. Tuy nhiên trình biên dịch sẽ không nhận được sự thay đổi đó nên vòng lặp vẫn tiếp tục thực hiện mà không kết thúc.

Để biến không bị optimize bởi trình biên dịch ta sử dụng từ khóa volatile.

Ví dụ:

#include <iostream> 
 
#include <thread>

using namespace std;

class Gadget
{
 
   public:
 
      Gadget()
      {
 
         _flag = false;
 
      }
 
      void Wait()
      {
 
         int val = 0;
 
         while (!_flag)
         {
 
            val++;
 
         }
  
      }
 
      void Wakeup()
      {
 
         _flag = true;
 
      }
 
   private:
 
      //biến _flag khai báo là volatile
      volatile bool _flag;
 
};

Gadget gaget;

void ThreadFunc();

int main()
{
 
   thread t(ThreadFunc);
 
   gaget.Wait();
 
   cout << "End wait!" << endl;
 
   t.join();
 
   return 0;
 
}

void ThreadFunc()
{
 
   cin.get();
 
   gaget.Wakeup();
 
   cout << "Wake up!" << endl;

} 

Ví dụ trên ta có thể thay đôi biến _flag không có volatile để xem kết quả.

Cài đặt optimize code trong Visual studio

Mặc định trong visual studio khi build ở chế độ debug thì optimize code bị disable, còn khi build ở chế độ release thì optimize code được enable. Tuy nhiên ta có thế cài đặt optimize code theo ý mình.

Click chuột phải vào project chọn Properties. Dialog property hiện lên chọn “C/C++ -> Optimization -> Optimization“. Click OK

Setup optimize code trong visual studio

Leave A Comment?