gpt4 book ai didi

c++ - 通过构造时获取的指针修改const对象

转载 作者:可可西里 更新时间:2023-11-01 15:51:51 28 4
gpt4 key购买 nike

我刚刚发现在没有任何 const_cast 的情况下修改 const 对象是多么容易黑魔法。考虑:

#include <iostream>

class Test {
public:
Test(int v)
:m_val{ v },
m_ptr{ &m_val }
{}

int get() const { return m_val; }
void set(int v) const { *m_ptr = v; }

private:
int m_val;
int* m_ptr;
};

int main()
{
const Test t{ 10 };

std::cout << t.get() << '\n';
t.set(0);
std::cout << t.get() << '\n';

return 0;
}

最新版本的 Clang、GCC 和 MSVC 不显示任何警告并产生预期的输出:

10 0

根据当前标准,这是明确定义的行为吗?如果未定义 m_val 会怎样类型为 std::aligned_storage_t<sizeof(int), alignof(int)>和构造函数 new 'ed int在里面?我相信在小型缓冲区优化方面,这是很常见的情况。

编辑

谢谢,看来又是搬起石头砸自己的脚。这似乎令人不安:

struct Test2 {
int i;
void operator()() { ++i; }
};

const std::function<void()> f{ Test2{ 10 } };
f();

在实现选择存储 Test2 时也是未定义的行为里面的物体 f (在 libc++ 和 Visual Studio 中就是这种情况)

最佳答案

const 强制执行“按位常量”,但您通常想要的是“逻辑常量”。

对于包含指针的对象,这意味着 const 成员函数不能修改指针本身,但可以修改指针所指的内容。换句话说,这些示例格式正确,但具有未定义的行为。

要获得逻辑常量,您 1) 使用 mutable(或有时使用 const_cast)允许修改不影响对象逻辑状态的成员(例如,缓存的值/内存),以及 2) 通常必须手动强制不通过指针写入数据(但如果它是一个拥有指针,则该所有权可能应该委托(delegate)给一个对象,该对象管理该对象的所有权数据,在这种情况下,将其设置为常量通常会阻止写入它拥有的数据)。

至于有一个非 const 指针指向本身可能已被 const 修改的数据的具体细节,好吧,你基本上只是得到一个与 const_cast 大致相同的东西的(持久)版本 通常用于:获取对数据的非常量访问权限,否则您只能使用 const 指针访问这些数据。您需要确保仅以不会导致问题的方式使用它(但仅拥有和/或写入该指针本身并不一定会导致问题)。

换句话说,我们这里有两个指向某些数据的独立指针。 this 允许您访问对象的数据。在 const 成员函数中,您只能通过 this 读取(不能)写入数据,除非(如上所述)它被标记为 mutable。在这种情况下,您正在保存指向相同数据的第二个指针。由于没有任何东西可以将其标记为指向 const 的指针,所以它不是,所以您可以非常量访问它指向的数据。

关于c++ - 通过构造时获取的指针修改const对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40294063/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com