C++ 遗留代码会改变常量指针。有什么正当理由吗?

C++ 遗留代码会改变常量指针。有什么正当理由吗?,c++,casting,constants,undefined-behavior,C++,Casting,Constants,Undefined Behavior,我有一些代码,多年来积累了很多粗糙的东西。它有一个类,看起来像: class Foo { public: Foo(int* data) : data_(data) { } Foo() : data_(nullptr) { } void loadFile(File* file); private: const int* data_; }; void Foo::loadFile(File* file) { file->loadToBuffer(const_cast&l

我有一些代码,多年来积累了很多粗糙的东西。它有一个类,看起来像:

class Foo {
public:
  Foo(int* data) : data_(data) { }

  Foo() : data_(nullptr) { }

  void loadFile(File* file);

private:
 const int* data_;
};

void Foo::loadFile(File* file) {
  file->loadToBuffer(const_cast<int**>(&data_));
}

void File::loadToBuffer(int** buf) {
  *buf = new int[1024];
  // Load the data...
}
class-Foo{
公众:
Foo(int*data):数据(data){
Foo()
作废加载文件(文件*文件);
私人:
常数int*数据_u2;;
};
void Foo::loadFile(File*File){
文件->加载缓冲(const_cast(&data));
}
无效文件::loadToBuffer(int**buf){
*buf=新整数[1024];
//加载数据。。。
}
我相信
const
成员最初是“正确”使用并在构造函数中初始化的,但随着时间的推移,添加了不符合该模式的其他初始化对象的方法,因此
const\u cast
被用作一种变通方法。实际的类非常大(数千行),并且初始化非常复杂,不可能以尊重
常量的方式将其分解出来


据我所知,这是未定义的行为,因此应该通过删除
数据上的
const
限定符来杀死它。但是这个代码已经运行了很长一段时间,没有引起任何明显的问题,所以我不确定我是否遗漏了什么——这种(错误地)使用
const
的行为在理论上或实践中是否可以接受?写这样的东西有什么可以想象的好处吗,还是说它还没有坏只是一个意外的惊喜?

这是一个指向常量int的指针,它可以指向int或常量int

const int* data_;
您可以更改数据(您可以将其指向另一个int/const int)

不能更改*数据(不能更改指定值)

在对其执行静态转换时,仅当数据指向不带常量的int时才允许。如果数据指向常量int,则静态强制转换将导致未定义的行为


因此,在这种情况下,代码很好,因为无论是使用Foo-first构造函数还是在loadToBuffer中,数据都只指向int(而不是const-int)

这是指向常量int的指针,它可以指向int或常量int

const int* data_;
您可以更改数据(您可以将其指向另一个int/const int)

不能更改*数据(不能更改指定值)

在对其执行静态转换时,仅当数据指向不带常量的int时才允许。如果数据指向常量int,则静态强制转换将导致未定义的行为


因此,在这种情况下,代码很好,因为无论是使用Foo-first构造函数还是在loadToBuffer中,数据都只指向int(而不是const-int)

file->loadToBuffer(&const_cast(数据))不应编译,因为您试图获取l值的地址。。或者使用Visual C++ 2015。@ China HythKl,我想这有助于揭示我的一些困惑---它是代码> COSTYSTCAST(和DATAAI)< /代码>。我想这就像是
&((int*)数据
将是C语言。谢谢你的澄清。修正了问题。
file->loadToBuffer(&const_cast(data)))不应编译,因为您试图获取l值的地址。。或者使用Visual C++ 2015。@ China HythKl,我想这有助于揭示我的一些困惑---它是代码> COSTYSTCAST(和DATAAI)< /代码>。我想这就像是
&((int*)数据
将是C语言。谢谢你的澄清。修正了问题。全部正确,但相关部分是
&const\u cast…
中的
。不能获取返回值的地址,它不是对象。与
int*ptr=&4;相同的错误是的,但我不确定这是否是相关部分。这可以通过将const_cast的结果赋给局部变量来轻松解决。如果将其赋给局部变量,就不会再修改
Foo::data
。当然,您可以先将
Foo::data
赋值给一个局部变量,然后再将其重新赋值,但为什么要费心第一步呢?只需创建一个正确类型的局部变量
int*tmp=nullptr
,不强制转换任何内容,调用
loadBuffer(&tmp)
,然后分配
data=tmp
(隐式强制转换为
const
)。这将失败,因为
LoadToBuffer
无法更改
int*
。对,对不起,实际上,不需要将int**作为参数,只需取int*(这仍然需要const_cast)。即使采用常量int*,也可以使用新的int[4]对其进行赋值,因为您可以更改所指的值,也可以指向非常量true,但相关部分是
&const\u cast中的
&
。不能获取返回值的地址,它不是对象。与
int*ptr=&4;相同的错误是的,但我不确定这是否是相关部分。这可以通过将const_cast的结果赋给局部变量来轻松解决。如果将其赋给局部变量,就不会再修改
Foo::data
。当然,您可以先将
Foo::data
赋值给一个局部变量,然后再将其重新赋值,但为什么要费心第一步呢?只需创建一个正确类型的局部变量
int*tmp=nullptr
,不强制转换任何内容,调用
loadBuffer(&tmp)
,然后分配
data=tmp
(隐式强制转换为
const
)。这将失败,因为
LoadToBuffer
无法更改
int*
。对,对不起,实际上,不需要将int**作为参数,只需取int*(这仍然需要const_cast)。即使采用常量int*,也可以使用新的int[4]对其进行赋值,因为您可以更改指向的值,也可以指向非常量