I've seen some methods like this:
void SomeClass::someMethod() const;
What does this const declaration do, and how can it help optimize a program?
Edit
I see that the first part of this question has been asked before... BUT, it still doesn't answer the second part: how would this optimize the program?
If the compiler knows that the fields of a class instance are not modified across a const member function call, it doesn't have to reload any fields that it may have kept in registers before the const function call.
This is sort of referred to the in C++ FAQ in the discussion on const_cast.
It tells the compiler that the method has no effect on the classes state; you can't assign to anything in it. Have a look at the C++ FAQ Lite 18.10.
The asm code that is generated for the const method will be the same if the const is there or not. const is a function of the compiler not the runtime, so if there are any performance gains I would think that the compilers optimizer might use the const as a hint for things like inlining or determining side effects for a possible optimization. So in short the optimizer might be able to help out a bit, but if the method is straight forward to begin with then I doubt that the code generated from the optimizer would be any different const or no const.
Here's an easy optimization I use (rather than hit and miss things like const) which take a second but pay off. Organize your class variables so that they fall on cache line boundaries a little better, and put your most accessed variables together. To do it just put your ints, doubles, floats, etc. together at the top of your class variable declarations and your odd sized variables at the bottom like so:
int foo;
int bar;
double baz;
SomeObject obj;
char ch[14];
It allows you to call the class member function on const objects:
class SomeClass
{
public:
void foo();
void bar() const;
}
SomeClass a;
const SomeClass b;
a.foo(); // ok
a.bar(); // ok
b.foo(); // ERROR -- foo() is not const
b.bar(); // ok -- bar() is const
There's also the volatile qualifier for use with volatile objects, and you can also make functions const volatile for use on const volatile objects, but those two are exceedingly rare.
It prevents someMethod from altering any member variable of an object of that class.
My first thought regarding optimization is that since the 'const' indicates that the instance's state hasn't changed, the compiler possibly has more freedom with respect to reordering nearby calls to methods on that instance.
Related
Before I start, this is not a style opinion question. I want to know why and if I really have to place storage modifiers before the function. Philosophical discussion follows.
A very friendly C++ grammar policeman once taught me always to place modifiers to objects after the doodad to be modified. For example:
int const myint; // good
const int myint; // bad
The idea of this, and I quite like his or her reasoning, is that the modifier will then always modify the property before it. So when we declare a method the logical convention is this:
const int const fun(); // bad
int const fun() const; // good
So assuming that this is the way I do things, and without starting a debate on this all over again, why do I have to place storage modifiers (such as static) before the function? So a const and static function next to each other will confusingly look like this:
int fun1() const;
static int fun2();
Given that, conceptually, the static and const keywords in this context have categorically related roles (they both modify what the function can and cannot do, to be broad) shouldn't similar grammar rules apply to them? I want to be able to do this:
int fun1() const;
int fun2() static; // why doesn't this work?
The reason is that static is an entirely different sort of thing from const.
Specifically, static specifies a storage class, while const is a cv-qualifier (or just qualifier, depending on the standard you're looking at).
As such, the rules for the two are rather different. As you've already found, one of the rules is that a storage class specifier needs to be nearly the first item in the declaration, and that only one storage class can be specified in most declarations (the sole exception of which I'm aware: you can specify thread_local along with either static or extern).
There is a big difference between declaring a static or virtual function and func() const, in that the first defines how the the function interacts to the object it is a member of, and the second form defines what it is allowed to do TO the object it is a member of.
And, yes, it's slightly confusing that one comes after the function prototype, and the other is before. I think that is because it would be even more confiusing if const char * const x = "abc" means something different than const char * const func() { return "abc"; } - and it is a good idea to keep the number of reserved words t a minimum in the language, so adding a "constfunc" or something like that to the reserved words was deemed a bad idea. By placing it after the () in the function declaration, it avoids confusion and allows the same word to be used for another purpose.
const does not actually modify the function, but the type of the implicit this pointer. All functions are immutable as far as the C++ type system is concerned (C++ does not provide any language support for self-modifying code).
For that reason it doesn't make sense to compare its position to either the return type or function modifiers.
I am trying to implement the use of a C++ library within my project that has not used const modifiers on its access functions. Up until now I have been using const in all of my code but this new library is causing two main problems:
Functions where the arguments are passed as const references cannot use the argument's access functions if these arguments are of a type defined by the library.
Classes with member objects of types defined by the library cannot use the access functions of these objects within a const function.
What is the best way to overcome this issue? The easiest solution would be to simply remove all use of const from my code but that would be quite frustrating to do.
Additional info: In this case I do have access to the source code and can see that the access functions do not modify anything. I omitted this information as I was interested in the more general case as well. For my scenario, const_cast appears to be the way to go
PS The library writer is not evil! It is more a bit of rough and ready code that he has kindly open sourced. I could ditch the library and use something more professional as others have noted. However, for this small time-constrained project, the simplicity of the interface to this library has made it the best choice.
How easy is it to tell whether the functions in the library actually modify anything or not?
If it's easy to tell, and they don't, then you can const_cast your const pointer/reference to non-const and call the library function. You might want to throw a wrapper around the library classes to do this for you, which is tedious and verbose but gets that code out of your classes. This wrapper could perhaps be a subclass that adds some const accessors, depending whether the way you use the library class allows that to work.
If it's hard to tell, or they do modify things, then you need to use non-const instances and references to the library classes in your code. mutable can help with those of type (2), but for those of type (1) you just need to pass non-const arguments around.
For an example of why it might be hard, consider that the library author might have written something like this:
struct Foo {
size_t times_accessed;
int value;
int get() {
++times_accessed;
return value;
}
};
Now, if you const_cast a const instance of Foo and call get(), you have undefined behavior[*]. So you have to be sure that get really doesn't modify the object it's called on. You could mitigate this a bit, by making sure that you never create any const instances of Foo, even though you do take const references to non-const instances. That way, when you const_cast and call get you at least don't cause UB. It might make your code confusing, that fields keep changing on objects that your functions claim not to modify.
[*] Why is it undefined behavior? It has to be, in order that the language can guarantee that the value of a const object never changes in a valid program. This guarantee allows the compiler to do useful things. For example it can put static const objects in read-only data sections, and it can optimize code using known values. It also means that a const integer object with a visible initializer is a compile-time constant, which the standard makes use of to let you use it as the size of an array, or a template argument. If it wasn't UB to modify a const object, then const objects wouldn't be constant, and these things wouldn't be possible:
#include <iostream>
struct Foo {
int a;
Foo(int a) : a(a) {}
};
void nobody_knows_what_this_does1(const int *p); // defined in another TU
void nobody_knows_what_this_does2(const int *p); // defined in another TU
int main() {
const Foo f(1);
Foo g(1);
nobody_knows_what_this_does1(&f.a);
nobody_knows_what_this_does2(&g.a);
int x;
if (std::cin >> x) {
std::cout << (x / f.a); // Optimization opportunity!
std::cout << (x / g.a); // Cannot optimize!
}
}
Because f is a const object, and hence f.a is a const object, the optimizer knows that f.a has value 1 when it's used at the end of the function. It could, if it chose, optimize away the division. It doesn't know the same thing about g.a: g is not a const object, a pointer to it has been passed into unknown code, so its value might have changed. So if you're the author of nobody_knows_what_this_does1 or nobody_knows_what_this_does2, and you're thinking of const_casting p and using it to modify its referand, then you can only do it if you somehow know that the referand is non-const. Which normally you don't, so normally you don't use const_cast.
I think you have the following options:
If you are sure the library is working as it should if it was using the const specifier, you could use const_cast<> to remove the const-ness of your objects when dealing with the library
Alternatively, you could make non-const copies of your const objects and pass those to the library, then update the changes to the non-const parts on your original objects
Search for another library that is const-correct
remove all const from your code (not recommended)
Another option is to copy your object into a modifiable temp and pitch it. This is probably the safest thing to do if you're in the circumstance where your class offers a copy constructor and it's not too expensive. This has been my preferred method when it's available, as I know it's 100% safe. Silly example:
int getInfoFromString(String& str); //what?? why isn't str const :(
So I do
String temp(str);
int stuffINeed = getInfoFromString(temp);
//happy
If the library's interface is not big, you can create a wrapper, where you would adjust your code to expected types, by either casting or making a copy of parameters, which are passed to library's functions.
But do not degrade your code in order to use the library.
Another suggestion: Are you familiar with the mutable keyword? If you use it correctly, it might actually accomplish exactly what you're trying to do, with exactly one word added to your code. This keyword can evoke religious opinion at the level of goto because it's probably used as a kludge for every hundred times that it's used because it really is the best design option. In your case, it's debatable which it is but I think it fits the spirit: your annoying library object is something that can be fake-modified without breaking the semantic const-ness of your methods, so go ahead.
class Outer {
mutable Inner inner;
public void foo() const {
inner.nonConstMethod(); //compiles because inner is mutable
}
};
I have a simple class:
class A {
public:
int get() const;
private:
void do_something();
int value;
}
int A::get() const {
return value;
}
The getter function is simple and straightforward. Getters are to use them, so in do_something I should use get() in order to access value. My question is: will compiler optimize-out the getter, so it will be equivalent to accessing the data directly? Or I still will gain performance if I access it directly (what would imply worse design)?
A::do_something()
{
x = get();
// or...
x = value;
}
When the method is not virtual, compilers can optimize it. Good compilers (with link-time optimization) can optimize even if the method is not inline and defined in separate .cpp file. Not so good ones can only do that if it's declared inside the class definition, or in the header file with inline keyword. For virtual methods, it depends, but most likely no.
The compiler will almost certainly inline such a trivial getter, if it's got access to the definition.
If the getter is defined as an inline function (either implicitly by defining it inside the class, or explicitly with the inline keyword), the compiler will usually inline it, and there will be no overhead in calling it.
It is, however, common for debug builds to disable inlining, which is perfectly valid since compilers are not required to inline anything.
Well, using get is usually a better design because it hides the actual logic involved in getting the value (today it's a field, tomorrow it may require more complex logic). As for performance, while accessing the value itself will always be at least as fast as using get, the compiler will most likely inline the call anyway.
First you would not be able to manipulate the value inside your object if you do not return a reference rather than the value:
int& get();
Now it returns a reference and can be altered. But imho this is not quite clean, you should also define a setter and use it to write back the altered value:
int get() const;
void set(int);
...
A::do_something()
{
x = get();
set(value);
}
The performance of the setter depends on your compiler. Most modern compilers are able to inline simple getters/setters, so there should not be any performance loss.
What is the simplest and least obtrusive way to indicate to the compiler, whether by means of compiler options, #defines, typedefs, or templates, that every time I say T, I really mean T const? I would prefer not to make use of an external preprocessor. Since I don't use the mutable keyword, that would be acceptable to repurpose to indicate mutable state.
Edit: Since the intent of this was mistaken entirely (and since I wasn't around for a few hours to clarify), let me explain. In essence, I just want to know what systems are available for manipulating the type system at compile time. I don't care if this creates nonstandard, bad, unmaintainable, useless code. I'm not going to use it in production. It's just a curiosity.
Potential (suboptimal) solutions so far:
// I presume redefinition of keywords is implementation-defined or illegal.
#define int int const
#define ptr * const
int i(0);
int ptr j(&i);
typedef int const Int;
typedef int const* const Intp;
Int i(0);
Intp j(&i);
template<class T>
struct C { typedef T const type; typedef T const* const ptr; };
C<int>::type i(0);
C<int>::ptr j(&i);
Take an open source C++ compiler and modify it.
I think the main reason for the downvotes is that people think you're trying to modify C++. Tell them instead you're creating a new language called "C-const" as a university project.
Personally I think it's an interesting idea - you can gain all sorts of performance and readability gains from immutable types - just look at most functional languages.
Even if you are able to do this (which I suspect you are not), think about other people reading your code. They are not likely to understand that everything is const and as a result are not likely to understand your code.
Are you trying to tell the compiler, or tell other people reading or using your code? The compiler won't do much anything different just because a user defined type is used const. Really, all it does is change the set of methods (user defined or implicit) that can be used with that object. In turn, that may allow the compiler to infer some optimizations on the run-time representation.
For class/struct types, you can make this clear to both the compiler and users by simply making every member const:
class Point {
// An immutable Point data object
public:
Point(int ix, int iy): x(ix), y(iy) { }
Point(const Point& p): x(p.x), y(p.y) { }
Point add(const Point& p) const;
int taxiDistance() const;
// etc... all const members
const int x, y; // const can only be init'd at construction time
private:
Point& operator=(const Point& p); // never implemented!
}
I would advice against this. If you manage to achieve you goal anyone (including you after some time) is surprised when he reads your code and it behaves different than he expects.
Please add the const modifier plain visible for everyone wherever it's needed. Your code is going to be read fare more often then it's going to be written!
You could keep the code standard C++ and devise an extra layer of type checking.
An empty MUTABLE macro could serve as an hint for the const checker. Explicit const may still be needed at places to make the code compile.
Given a declaration like this:
class A {
public:
void Foo() const;
};
What does it mean?
Google turns up this:
Member functions should be declared with the const keyword after them if they can operate on a const (this) object. If the function is not declared const, in can not be applied to a const object, and the compiler will give an error message.
But I find that somewhat confusing; can anyone out there put it in better terms?
Thanks.
Consider a variation of your class A.
class A {
public:
void Foo() const;
void Moo();
private:
int m_nState; // Could add mutable keyword if desired
int GetState() const { return m_nState; }
void SetState(int val) { m_nState = val; }
};
const A *A1 = new A();
A *A2 = new A();
A1->Foo(); // OK
A2->Foo(); // OK
A1->Moo(); // Error - Not allowed to call non-const function on const object instance
A2->Moo(); // OK
The const keyword on a function declaration indicates to the compiler that the function is contractually obligated not to modify the state of A. Thus you are unable to call non-const functions within A::Foo nor change the value of member variables.
To illustrate, Foo() may not invoke A::SetState as it is declared non-const, A::GetState however is ok because it is explicitly declared const. The member m_nState may not be changed either unless declared with the keyword mutable.
One example of this usage of const is for 'getter' functions to obtain the value of member variables.
#1800 Information: I forgot about mutable!
The mutable keyword instructs the compiler to accept modifications to the member variable which would otherwise cause a compiler error. It is used when the function needs to modify state but the object is considered logically consistent (constant) regardless of the modification.
This is not an answer, just a side comment. It is highly recommended to declare variables and constants const as much as possible.
This communicates your intent to users of your class (even/especially yourself).
The compiler will keep you honest to those intentions. -- i.e., it's like compiler checked documentation.
By definition, this prevents state changes you weren't expecting and can, possibly, allow you to make reasonable assumptions while in your methods.
const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).
If you're using a language with static, compile time checks it's a great idea to make as much use of them as possible... it's just another kind of testing really.
Functions with const qualifier are not allowed to modify any member variables. For example:
class A
{
int x;
mutable int y;
void f() const
{
x = 1; // error
y = 1; // ok because y is mutable
}
};
C++ objects can be declared to be const:
const A obj = new A();
When an object is const, the only member functions that can be called on that object are functions declared to be const. Making an object const can be interpreted as making the object readonly. A const object cannot be changed, i.e. no data members of the object can be changed. Declaring a member function const means that the function is not allowed to make any changes to the data members of the object.
Two suggested best practices from experience:
(1) Declare const functions whenever possible. At first, I found this to be just extra work, but then I started passing my objects to functions with signatures like f(const Object& o), and suddenly the compiler barfed on a line in f such as o.GetAValue(), because I hadn't marked GetAValue as a const function. This can surprise you especially when you subclass something and don't mark your version of the virtual methods as const - in that case the compile could fail on some function you've never heard of before that was written for the base class.
(2) Avoid mutable variables when it's practical. A tempting trap can be to allow read operations to alter state, such as if you're building a "smart" object that does lazy or asynchronous i/o operations. If you can manage this with only one small mutable variable (like a bool), then, in my experience, this makes sense. However, if you find yourself marking every member variable as mutable in order to keep some operations const, you're defeating the purpose of the const keyword. What can go wrong is that a function which thinks it's not altering your class (since it only calls const methods) my invoke a bug in your code, and it could take a lot of effort to even realize this bug is in your class, since the other coder (rightly) assumes your data is const because he or she is only calling const methods.
const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).
Additionally, you will easily run into problems if methods that should be const aren't! This will creep through the code as well, and make it worse and worse.
that will cause the method to not be able to alter any member variables of the object