簡體   English   中英

volatile、const、volatile const 和“兩者都不是”類型之間的轉換

[英]Conversions between volatile, const, volatile const, and "neither" types

C++(11) 標准對 volatile、const、volatile const 和“兩者都不是”類型之間的轉換有什么看法? 我知道將 const 類型分配給非常量和非易失性類型是明確定義和可接受的,但是以下類型(其中 T 是某種類型)之間的轉換呢?

// T
T
T volatile
T const 
T volatile const 

// Pointer-to-T
T*
T volatile*
T const*
T volatile const*

// Volatile pointer-to-T
T* volatile
T volatile* volatile
T const* volatile
T volatile const* volatile

// Const pointer-to-T
T* const
T volatile* const
T const* const
T volatile const* const

// Volatile const pointer-to-T
T* volatile const
T volatile* volatile const
T const* volatile const
T volatile const* volatile const

作為一個簡單的例子,請考慮以下代碼:

T volatile a;
T const b;

a = b; // implicit conversion from const to volatile; okay?

template<typename T>
void fcn(T& t)
{
    t = b; // implicit conversion from const to non-const, which I assume is okay
}
fcn(a); // implicit conversion from volatile to non-volatile; okay?

你可以分配給什么?

您始終可以將 volatile 值分配給非常量值。 您還可以將 const 和非常量值分配給 volatile 值。 你永遠不能給 const 值賦值,因為它們是 const 的。

是否發生轉換?

不 - 它只是在做一項任務。

為什么是這樣?

volatile意味着無法優化對對象的任何訪問。 實際上很少有需要或使用volatile情況。 這些情況是:

  • 當您對操作計時,並且不希望優化計算時(請為此使用基准測試庫。不要自己動手)
  • 當您進行內存映射 IO 時。 在這種情況下,您要保證讀取和寫入不會被優化掉,因此可以使用 volatile。

因此,必須可以將volatile分配給常規對象,反之亦然。 但是,與此同時,不應該將 volatile 引用隱式轉換為常規引用,因為這可能會導致讀取和寫入被優化掉。

常量呢?

您可以將 const 的內容分配給任何東西,但不能將任何內容分配給 const(因為它是 const)。

a = b; // implicit conversion from const to volatile; okay?

是否“正常”取決於類型T

這里發生的是左值到右值的轉換。 這是標准規則所說的:

[conv.lval]

非函數、非數組類型 T 的泛左值可以轉換為純右值。 如果 T 是一個不完整的類型,那么需要這種轉換的程序就是格式錯誤的。 如果 T 是非類類型,則純右值的類型是 T 的 cv 非限定版本。否則,純右值的類型是 T。

因此,例如,如果T不是類類型,那么從T const b轉換的純右值將是T ,在這種情況下,它與分配的變量的類型相同。 所以,只要T是可賦值的(即不是 const),它就“沒問題”。

對於類類型,賦值是否“可以”取決於類具有的賦值運算符類型。 隱式賦值運算符不是 volatile 限定的,因此示例賦值不會“好”。 它將是格式錯誤的。 但是有可能讓用戶聲明一個 volatile 限定的賦值運算符,盡管這種情況並不常見。

關於fcn(a); // implicit conversion from volatile to non-volatile; okay? fcn(a); // implicit conversion from volatile to non-volatile; okay? ,根據this是不行的,因為它會導致從非易失性類型引用易失性類型:

C 標准 6.7.3 [ISO/IEC 9899:2011] 指出

如果嘗試通過使用具有非 volatile 限定類型的左值來引用使用 volatile 限定類型定義的對象,則行為未定義。


另外,雖然我沒有引用,但我相信指針之間的賦值和轉換必須具有它們指向的相同的 volatile-/const- 限定類型(即*必須匹配之前的const s/ volatile s):

T volatile* volatile t; T volatile* volatile const t1 = t; // okay; initializing const with non-const T* volatile t2 = t; // not okay; t and t2 point to different types T volatile const* volatile t3 = t; // not okay; t and t3 point to different types

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM