c++ - 在 const 成员不良做法或 UB 中修改 const 变量?

标签 c++

下面的代码是不好的做法还是未定义的行为?本质上,我正在调用 const func 来修改未标记为可变的成员。链接到 demo

感谢 Mehrdad 启发了这个问题(他的问题 Does this code subvert the C++ type system? )和 david 对演示的小改进。

#include <iostream>
using namespace std;

struct BreakConst
{
    int v;
    int *p;
    BreakConst() { v = 0; p = &v; } 
    void break_stuff() const { ++*p; }
};
void f(const BreakConst& bc) {
    bc.break_stuff();
}

大多数答案所基于的原始版本:

由 David Rodríguez、jpalecek、Mehrdad 回答
是的:这是“未定义的行为”

int main()
{
    const BreakConst bc;
    cout << bc.v << endl;   // 0
    bc.break_stuff();       // O:)
    cout << bc.v << endl;   // 1

    return 0;
}

新的备选问题:

梅赫达德回答
否:这不是“未定义的行为”

int main()
{
    BreakConst bc;
    cout << bc.v << endl;   // 0
    f(bc);                  // O:)
    cout << bc.v << endl;   // 1

    return 0;
}

结果:

0
1

最佳答案

在这种情况下,我会说这是未定义的行为。 bc 是一个 const 对象,所以它的所有子对象(较少的 mutable)1,因此 bc.v 也应该是并且修改 const 对象,无论如何实现,都是 UB2

[1] C++03 3.9.3/3:

Each non-static, non-mutable, non-reference data member of a const-qualified class object is const- qualified...

[2] C++03 7.1.5.1/4:

Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.

EDIT 回应问题的编辑:不,代码的修改版本不会导致未定义的行为。这可能是不好的做法,但实际上有时可能很有用。你可以,例如。使用它通过 const-iterators (DRY) 为您的类实现迭代器:

class const_iterator
{
public:
  const T& dereference() const; // complicated
};

class iterator : public const_iterator
{
public:
  T& dereference() const { return const_cast<T&>(const_iterator::dereference()); }
};

当然,这依赖于 iterator 只能由可变容器构成、const 和非常量版本没有区别(没有 COW 等)等事实,但是相当普遍。

关于c++ - 在 const 成员不良做法或 UB 中修改 const 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11091385/

相关文章:

c++ - 对指针不了解

c++ - 我在不使用指针的情况下得到 "Segmentation Fault"。怎么了?

c++ - 包含引用另一个 vector 内容的 vector 的对象

c++ - 在 C++ 中使用静态变量访问数组位置

c++ - 从 URL 请求以编程方式下载谷歌街景全景图

c++ - C++算法中 "functions"和 "function-like entities"有什么区别?

c++ - 基类的多重虚继承和构造函数调用

c++ - 链接器错误 : already defined

c++ - 获取 dll 路径/字符串问题(C++ 初学者)

c# - 使用 WinForms 扩展旧版 C++ Windows 应用程序