[英]Why can I modify const_cast-ed object in constexpr function?
我一直以為:
const_cast
ed 變量是 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.