簡體   English   中英

static_cast 對 void* 的 const 引用

[英]static_cast const reference to void*

我有一個對 void* 的 const 引用:

void* p;
void* const& x = p;

我想將它轉換為對 T* 的 const 引用(對於某些struct T {}; )。 在我能想到的三種方法中,我默認的static_cast選擇不起作用:

T* const& y = static_cast<T* const&>(x);       // doesn't work
T* const& y = reinterpret_cast<T* const&>(x);  // works
T* const& y = (T* const&) x;                   // works

GCC 給出以下錯誤:

error: invalid static_cast from type ‘void* const’ to type ‘T* const&’
       T* const& y = static_cast<T* const&>(x);

我想了解它的含義,以及是否有辦法解決它。


編輯(2019-11-26):

評論和答案中有關於T* const& (和void* const& )是否為

  1. T*的 const 引用; 或者
  2. const T*的引用。

評論中的共識似乎是選項 2。但是從以下示例中,在我看來它是選項 1。

假設我有一個帶有非常量函數f() T類:

struct T
{
  void f() {};  // NB: non-const
};

我們可以考慮兩種選擇:

const T*  x;
T* const& y;

通過它們調用f()會產生不同的效果:

x->f();   // compile-time error (passing ‘const T’ as ‘this’ argument discards qualifiers)
y->f();   // works fine

這不表明選項 1 是正確的嗎? 有人可以為我調和嗎?

您不能將引用綁定到任何其他類型(除了相同類型的較少 cv 限定版本或某些涉及通過特殊類型(如unsigned char& )讀取單個字節的微妙事物)。 如果您使用reinterpret_cast (包括通過 C 風格的強制轉換)強制執行該問題,則使用結果(而不是通過將其返回)是未定義的行為。

您可以(僅使用static_cast )將void*轉換為T* ,並且您可以提供諸如

const auto y=[&] {return static_cast<T*>(p);};

這樣您就可以通過稍后在任何地方編寫y()來跟蹤p的當前值。 (由於它按值返回,因此您確實無法根據需要編寫y()=new T 。)

這就是語言轉換的工作方式。 這是一個簡單的,缺少概述的內容:

  • const_cast在具有不同cv資格的類型之間轉換。
  • static_cast用於安全轉換。 整數轉換,轉換運算符或轉換構造函數是static_cast可以執行的一些示例。
  • dynamic_cast適用於多態
  • reinterpret_cast是不得已的選擇,通過重新解釋基礎位模式,基本上可以進行任何轉換。
  • 顯式C樣式轉換被認為是C的遺留物。它將在上下文中使用“最佳”轉換。 在您的示例中,它等效於reinterpret_cast

void*T*轉換(都保存cv)是有效的,前提是原始指針的類型為T*又在指向的位置處存在類型為T的對象。 如您所見,如果條件不成立,則轉換是“危險的”,即您擁有UB(無效程序)。 因此,您只能使用reinterpret_cast做到這一點。

查看不想通過某個指針修改值的原始問題,以下應該有效。 模板化它應該給出相同的結果。 如果需要,請引入參考文獻,但結果相同。

void myfunc1(int* intptr)
{
    (*intptr)++;
    std::cout << "In myfunc1 "<< *intptr<<"\n";
}

void myfunc2(const int* intptr)
{
    //(*intptr)++; //modification not possible
    std::cout << "In myfunc2 " << *intptr << "\n";
}

int main()
{       
    int* val = new int;
    *val = 32;

    void*  p = val; 

    std::cout << "Before myfunc1 " << *val << "\n";
    myfunc1(static_cast<int*>(p));
    std::cout << "After myfunc1 "<<*val<<"\n";

    //no modification via pointer to const
    const int* x = static_cast<const int*>(p);
    myfunc2(x);
    std::cout << "After myfunc2 " << *val << "\n";

沒有const參考。 在C ++中, 引用是不可分配的(只能對其進行初始化)。 同樣, void* const&並不意味着對void *的const引用。 相反,它意味着對指向void的const指針的引用。 在下面的語句中,您只是初始化一個引用,因此您無需在static_cast提及引用。

T* const& y = static_cast<T* const&>(x);

正確的形式是:

T* const& y = static_cast<T* const>(x);

更新#1

評論和答案中有一個討論,關於T * const&(和void * const&)是否為

1和2都不是。請注意const T*T* const不同。 前者是指向const T的非const指針,而后者是指向非const T的const指針。因此, T* const&表示對指向非const T的const指針的引用。

同樣關於以下示例,

struct T
{
  void f() {};  // NB: non-const
};

給定const T* x; ,則無法調用x->f(); 因為x是指向const T的指針,但是函數f需要一個非const T,所以您不能使用const變量來初始化非const變量,因為這會丟棄const限定符。

暫無
暫無

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

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