簡體   English   中英

為什么我可以在 constexpr 函數中修改 const_cast-ed 對象?

[英]Why can I modify const_cast-ed object in constexpr function?

我一直以為:

  • 寫入const_cast ed 變量是 UB
  • constexpr 中不允許使用 UB

所以我很困惑為什么這段代碼會編譯

constexpr int fn(){
    int v = 42;
    return [v]() {
        const_cast<int&>(v)+=5;
        return v;
    }();
}
static constexpr auto val = fn();
int main() {
    return val;
}

注意:我知道沒有理由不允許這樣做,因為結果應該是顯而易見的,我對為什么允許這樣做的法律解釋更感興趣。

這部分是真的:

constexpr 中不允許使用 UB

這部分不是:

寫入const_cast -ed 變量是 UB

實際規則是,來自[dcl.type.cv]/4

任何在其生命周期 ([basic.life]) 期間修改 ([expr.ass], [expr.post.incr], [expr.pre.incr]) 的嘗試都會導致 const 對象 ([basic.type.qualifier])在未定義的行為中。

請注意,相關部分是對象是否為const - 而不是您到達它的任何路徑是否為const 在這種情況下, v不是const對象,也不是復制它時在 lambda 中創建的對象。

但是,如果您將v聲明為const ,那么在 lambda 中聲明的那個也將被聲明為const ,因此嘗試修改它將是未定義的行為。 結果,您的代碼將不再編譯。

lambda 表達式轉換為類似於以下內容:

struct unnamed {
    int v;
    int operator()() const {
       const_cast<int&>(v)+=5;
       return v;
    }
};

沒有const_cast你不能在operator()內部修改v因為運算符是一個const方法,但v本身不是const

相同的情況

struct foo {
    int x = 0;
    void operator() const {
        const_cast<int&>(x) += 42;
    }
};

那么這是“好的”:

foo f;
f();

雖然這是未定義的:

const foo f;
f();

暫無
暫無

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

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