According to my small tests this code works. But, does it have undefined behaviour? Modifying the const object through the use of const_cast resulted in run-time access violations in my previous tests, but I can't remember how they were different. So, is there fundamentally something wrong here or not?
// 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");
}
(Notice that sizeof(bigLut_t) is too much to fit into the stack.)
EDIT: I actually like the idea in ybungalobill's small comment best for a method of initializing these big objects:
// 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;
}
}
You modify an object defined as const. It doesn't matter when you do it, during initialization or not, it's still undefined behavior. Removing constness with const_cast is defined only if the const pointer was obtained from a non-const pointer to that object at some earlier stage. That's not your case.
The best thing you can do is
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();
and hopefully the compiler will optimize out the static temporary.
You are misusing the const_cast operator which is unfortunately possible, and in this case generates undefined behaviour... You can use dynamic initializer for constBigLut
by invoking its implicit copy constructor (assuming that boost::array
is the same concept as std::array
):
struct bigLut_tinit {
bigLut_t BigLut;
bigLut_tinit() {
for(int i = 0; i < 100000; ++i) {
BigLut[i] = i;
}
}
};
const bigLut_tinit constBigLut;
Edit: Seems that VC++10 perfectly applies RVO, so that the temporary is directly moved into the static duration object. So imho no need to declare local statics or references to tempraries...
Edit 2: Yeah, I missed the size issue. Recommend wrapping into a non-trivial type with constructor as above...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With