Frankly, I find it less confusing if a variable is either const
or not, than if this can change.
To elaborate a bit on this: The reason you usually want to do this is because you cannot initialize a const
variable the way you want to. std::vector
is a good example of this. Well, for once, the next standard introduces a universal initialization syntax that makes this possible:
const std::vector<int> cvi = { 1, 2, 3, 4, 5, 42 };
However, even without C++1x' stuff at hand, and even with types that disallow this initialization syntax, you can always create a helper function to do what you want:
const std::vector<int>& cvi = create_my_vector();
or, if you want to be fancy:
const std::vector<int>& cvi = compile_time_list<1,2,3,4,5,42>::create_vector();
Note the &
. There's no point in copying the result of the function call, since binding an rvalue to a const
reference extends its lifetime until the end of the reference's lifetime.
Of course, recompiling with a compiler that supports C++1x' move semantics will render such optimizations pretty much needless. But binding an rvlaue to a const
reference might still be faster than moving a vector and is unlikely to be slower.
With C++1x, you might also create lambda functions doing this one the fly. C++ just provides an incredibly huge arsenal of tools. IME, no matter how hard you have thought, someone else ought to come up with yet another idea to do the same thing. And often a better one than yours.
However, IME this problem usually only comes with too much code in too few functions anyway. And then it doesn't only apply to constness, but also to similar traits - like what a reference refers to.
A classic is the use-one-of-several-possible-streams. Instead of this
int main(int argc, char* argv[])
{
std::istream* istrm = NULL;
std::ifstream ifs;
if( argc > 1 )
{
ifs.open( argv[1] );
if( ifs.good() )
istrm = &ifs;
}
if( !istrm )
istrm = &std::cin;
while( istrm->good() )
{
// reading from *istrm implemented here
}
return 0;
}
just split the concerns into 1) figuring out where to read from and 2) the actual reading:
int read(std::istream& is)
{
while( is.good() )
{
// reading from is implemented here
}
return 0;
}
int main(int argc, char* argv[])
{
if( argc > 1 )
{
std::ifstream ifs( argv[1] );
if( ifs.good() )
return read(ifs);
}
return read(std::cin);
}
I have yet to see a real-world example of a variable that wasn't as constant as it could have been which couldn't be fixed by separating of concerns.