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]对其进行赋值,因为您可以更改指向的值,也可以指向非常量