通过const_cast的const初始化是否具有未定义的行为?
-
28-09-2019 - |
题
根据我的小测试,此代码有效。但是,它有不确定的行为吗?通过使用const_cast修改const对象会导致我以前的测试中的运行时访问违规行为,但我不记得它们与众不同。那么,这里有根本上有问题吗?
// test.h
#pragma once
#include <boost/array.hpp>
typedef boost::array<int,100000> bigLut_t;
extern const bigLut_t constBigLut;
// test.cpp
#include "test.h"
bigLut_t& initializeConstBigLut()
{
bigLut_t* pBigLut = const_cast<bigLut_t*>( &constBigLut );
for(int i = 0; i < 100000; ++i) {
pBigLut->at(i) = i;
}
return const_cast<bigLut_t&>(constBigLut);
}
const bigLut_t constBigLut = initializeConstBigLut();
// const_test.cpp
#include <iostream>
#include "test.h"
void main()
{
for(int i = 0; i < 100; ++i) {
std::cout << constBigLut[i] << std::endl;
}
system("pause");
}
(请注意,大小(Biglut_t)太多了,无法适应堆栈。)
编辑:我实际上喜欢Ybungalobill的小评论中的想法,最好是初始化这些大对象的方法:
// test.h
#pragma once
#include <boost/array.hpp>
extern const struct BigLut : public boost::array<int,100000> {
BigLut();
} constBigLut;
// test.cpp
#include "test.h"
const BigLut constBigLut;
BigLut::BigLut()
{
for(int i = 0; i < 100000; ++i) {
this->at(i) = i;
}
}
解决方案
您修改定义为const的对象。当您进行初始化时,它仍然无关紧要,它仍然是不确定的行为。仅在较早的某个阶段从非const指针获得const指针时,才定义使用const_cast删除constness。那不是你的情况。
您能做的最好的事情是
const bigLut_t& initializeConstBigLut()
{
static bigLut_t bigLot;
for(int i = 0; i < 100000; ++i) {
bigLut.at(i) = i;
}
return bigLut;
}
const bigLut_t constBigLut = initializeConstBigLut();
希望编译器能够优化静态临时性。
其他提示
您正在滥用const_cast操作员,这是不幸的,在这种情况下,您可以生成未定义的行为...您可以使用动态初始器 constBigLut
通过调用其隐式复制构造函数(假设 boost::array
与 std::array
):
struct bigLut_tinit {
bigLut_t BigLut;
bigLut_tinit() {
for(int i = 0; i < 100000; ++i) {
BigLut[i] = i;
}
}
};
const bigLut_tinit constBigLut;
编辑:似乎VC ++ 10完美地应用了RVO,因此临时性直接移动到静态持续时间对象中。因此,恕我直言,无需声明当地的静态或提及特姆普里斯...
编辑2:是的,我错过了大小问题。建议用上述构造函数包装成非平凡的类型...
它是UB,因为该数组可以存储在ROM中。
您可以这样做:
// test.h
#include <boost/array.hpp>
typedef boost::array<int,100000> bigLut_t;
const bigLut_t& Lut();
// test.cpp
#include "test.h"
bool initialized=false;
const bigLut_t& Lut()
{
static bigLut_t lut;
if (!initialized)
{
for(int i = 0; i < 100000; ++i) {
lut.at(i) = i;
}
}
return lut;
}
不隶属于 StackOverflow