如果实际对象不是const,则具有写操作的const_cast(this)是否具有未定义的行为?

时间:2019-07-11 12:55:49

标签: c++ language-lawyer

我对这个问题的回答是我对另一个问题的回答:https://stackoverflow.com/a/56989169/2492801

如果我有一个实际上不是public void steptwo() { LayoutInflater inflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE); View customView = inflater.inflate(R.layout.popup_observedproperty,null); mPopupWindow = new PopupWindow( customView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT ); String[] countryNameList = {"India", "China", "Australia", "New Zealand", "England", "Pakistan"}; ArrayAdapter<String> adapter = new ArrayAdapter<String>(customView.getContext(), android.R.layout.simple_dropdown_item_1line, countryNameList); AutoCompleteTextView textView = (AutoCompleteTextView) customView.findViewById(R.id.autoCompleteTextView); textView.setText("New"); textView.setAdapter(adapter); textView.setThreshold(1); if(Build.VERSION.SDK_INT>=21){ mPopupWindow.setElevation(5.0f); } mPopupWindow.setFocusable(true); mPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); mPopupWindow.showAtLocation(mRelativeLayout, Gravity.CENTER,0,0); } 的对象,但是调用了其const方法之一,则在方法const中当然是this。如果我const离开其常数,并将其传递给对const_cast所指向的对象执行写操作的另一种方法,那是不确定的行为吗?

如果确实如此,我不会感到惊讶,因为this实际上是this方法中的const。另一方面,对象本身不是const,因此一般不禁止写操作。

对我来说,重要的是要知道如何处理我的其他问题中所述的问题。谢谢!

3 个答案:

答案 0 :(得分:8)

这不是不确定的。这正是const_cast的目的。只要对象本身不是非const,那么您就可以使用const_cast将该对象抛弃,并与非const指针进行相同的操作。

请注意,const_cast通常被认为是代码异味,可能表明设计不好。


As the standard says

  

在非static([class.mfct])成员函数的主体中,   关键字this是一个prvalue,其值是指向以下对象的指针   该函数被调用。成员函数中的此类型   类XX*。如果成员函数声明为const,则类型为   这是常量X*,如果将成员函数声明为volatile,则   其类型为volatile X*,并且如果声明了成员函数   const volatile,其类型为const volatile X*

在您的情况下,this的类型为const X*,即使对象本身不是非{const


关于const_cast的标准says this

  

对于两个类似的类型T1T2,类型T1的prvalue可以是   使用T2显式转换为类型const_­cast。的   const_­cast的结果引用原始实体。

因此,从const X*投射到X*也是合法的。


最后,it says(尽管有注释):

  

[注:根据对象的类型,通过   由a产生的数据成员的指针,左值或指针   抛弃const限定符的const_­cast可能会产生未定义的   行为([dcl.type.cv])。 —注释]

还有[dcl.type.cv] tells us

  

任何修改尝试([expr.ass],[expr.post.incr],[expr.pre.incr])   一个const对象([basic.type.qualifier])在其生存期内   ([basic.life])导致行为不确定。

幸运的是,我们的this指向一个非const对象,因此强制转换并通过新的非const指针修改该对象不会触发未定义的行为。


抱歉。

答案 1 :(得分:-1)

const_cast仅更改类型,但不更改此指针的二进制表示形式。因此,仅当被调用的成员函数被const覆盖时,行为才会改变。因此,您的问题的答案为否。

答案 2 :(得分:-1)

因此const_cast的目的是允许这种类型的操纵,并且您应该以程序员的身份知道它是否安全。

如果您有一个带有“可接受”成员方法的聚合对象,可能会出错。没有构造函数,析构函数,虚拟函数,可变成员,本身不是聚合的成员,也不能派生它。

此类对象的实例可以在静态空间中声明为常量,并且编译器可以将该对象实例化到预定义的不可变内存块中。在该对象上执行const_cast并尝试使用全局函数或从成员函数对其进行修改,将导致“未定义的行为”,这可能是一个例外,可能是无法捕获的错误,几乎肯定会导致程序终止。