Would it make sense to have a "constify
" operation in C/C++
that makes a variable const
?
Here is an example where it could be useful, where obviously we don't want to declare it const
yet in the first line:
std::vector<int> v;
v.push_back(5);
constify v; // now it's const
Currently, without such a possibility, you'd have to introduce another variable to get the same effect:
std::vector<int> v0;
v0.push_back(5);
const std::vector<int>& v = v0;
That's more confusing since it adds a new name into the scope and you need to make it a reference to avoid copying the whole vector (or use swap
?).
const correctness can't improve performance because const_cast and mutable are in the language, and allow code to conformingly break the rules. This gets even worse in C++11, where your const data may e.g. be a pointer to a std::atomic , meaning the compiler has to respect changes made by other threads.
The benefit of const correctness is that it prevents you from inadvertently modifying something you didn't expect would be modified.
Variables can be declared as constants by using the “const” keyword before the datatype of the variable. The constant variables can be initialized once only. The default value of constant variables are zero.
The const keyword specifies that a variable's value is constant and tells the compiler to prevent the programmer from modifying it.
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.
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