What is the difference between these two terms, and why do I need mutable?
"Physical" constness comes from declaring an object const, and could, in principle, be enforced by placing the object in read-only memory, so it cannot change. Attempting to change it will cause undefined behaviour; it might change, or it might not, or it might trigger a protection fault, or it might melt the memory chip.
"Logical" constness comes from declaring a reference or pointer const, and is enforced by the compiler. The object itself may or may not be "physically" const, but the reference cannot be used to modify it without a cast. If the object is not "physically" const, then C++ allows you to modify it, using const_cast to circumvent the protection.
A mutable class member can be modified even if the class object itself (or the reference or pointer used to access it) is const. Examples of good uses of this are a mutex that must be locked during a read operation, and a cache to store the result of an expensive read operation. In both cases, the operation itself should be a const function (since it doesn't affect the visible state of the object), but it needs to modify the mutex or the cache, so these need to be mutable. It can also be abused to make the object visibly change when logically it shouldn't, so use it with care; only declare members mutable if they don't form part of the externally visible state.
You need mutable when there are fields in an object that can be considered "internal", i.e. any external user of the class cannot determine the value of these fields. The class might need to write to these fields even though the instance is considered constant, i.e. not changing.
Consider a hard drive; its cache is an example of such state. The cache is written to when data is read from the actual disk.
This is not possible to express cleanly in C++ without making the corresponding members mutable, to allow them to be changed even in methods marked const. As pointed out in a comment, you can always reach for the hammer and use a const_cast<> to remove the const-ness, but that is of course cheating. :)
Scott Meyers, Effective C++, Item 3:
Use const whenever possible
has an excellent discussion (with examples) on this topic. Its hard to write better than Scott!
Note also that physical-constness is also known as bitwise-constness.
Some code for people who want to try out the effects of physical constness theirselfes:
#include <type_traits>
using namespace std;
using type = int const;
type &f();
int main()
{
const_cast<remove_const_t<type> &>(f()) = 123;
}
#if defined(__GNUC__) || defined(__llvm__)
__attribute__((noinline))
#elif defined(_MSC_VER)
__declspec(noinline)
#endif
type &f()
{
static type i = 0;
return i;
}
Under Linux and Windows this program crashes until you drop the const-specifier with type.
I respectfully disagree with Mike Seymour's answer:
A member function of a class can be defined as a const function, meaning that it will not modify any internal state of the object (except for members that are marked mutable, which becomes an important issue when we talk later about "logical" const-ness). That is the actual definition of "physical" const-ness. But even though a function is marked const, it may be logically modifying the objects state. Consider the following example:
#include <iostream>
using namespace std;
class Foo
{
private:
int *ip;
public:
Foo(int i) {
ip = new int(i);
}
virtual ~Foo() {
delete ip;
}
void modifyState(int i) const {
*ip = i;
}
int getI(void) const {
return *ip;
}
};
int main(int argc, char *argv[])
{
Foo foo(7);
cout << foo.getI() << endl;
foo.modifyState(9);
cout << foo.getI() << endl;
return 0;
}
Prints:
7
9
Member function modifyState does not modify member ip, so it satisfies the requirements for physical const-ness. But who can argue that since it is modifying what ip points to that the logical state has not been changed? So even though this function satisfies the requirements for physical cont-ness, it does not satisfy logical const-ness since what function getI will return has been changed by the call to modifyState.
Conversely, we can physically modify an object's member, but the state of the object as it appears to the outside world via its interface has not changed. Consider the following example where const functions getCelsiusTemperature and getFahrenheitTemperature modify mutable state but do not modify the object's logical state:
#include <iostream>
using namespace std;
class Temperature
{
private:
mutable float temperature;
mutable bool is_celsius;
public:
Temperature(double temperature, bool is_celsius=true) {
this->temperature = temperature;
this->is_celsius = is_celsius;
}
double getCelsiusTemperature(void) const {
if (!this->is_celsius) {
// convert to Celsius:
this->temperature = (this->temperature - 32.0) * 5.0 / 9.0;
this->is_celsius = true;
}
return this->temperature;
}
const double getFahrenheitTemperature(void) const {
if (this->is_celsius) {
// convert to Fahrenheit:
this->temperature = this->temperature * 9.0 / 5.0 + 32.0;
this->is_celsius = false;
}
return this->temperature;
}
};
int main(int argc, char *argv[])
{
const Temperature t(100, true);
cout << t.getCelsiusTemperature() << endl;
cout << t.getFahrenheitTemperature() << endl;
cout << t.getCelsiusTemperature() << endl;
return 0;
}
Prints:
100
212
100
Related
I am new to C++, and was wondering what I am doing wrong.
I am trying to create a text-based adventure game that keeps track of player stats using an add or remove function. Currently, my function does not add five points to trust and I am trying to get it to.
#include "function.h"
using namespace std;
int main() {
double trust=100;
editPlayer user(100);
//asks user choice
cin >> firstChoice;
if (firstChoice == 1) {
user.addTrust(trust);
cout << trust;
Here is my function.cpp only using trust as an example:
#include "function.h"
editPlayer::editPlayer(double trust) {
}
void editPlayer::addTrust(double trust){
trust +=5;
}
void editPlayer::removeTrust(double trust){
trust -=5;
}
And here is my function.h:
#include<iostream>
#include<string>
using namespace std;
class editPlayer{
public:
editPlayer(double trust);
void addTrust(double);
void removeTrust(double);
};
Lets take your addTrust function:
void editPlayer::addTrust(double trust) {
trust += 5;
}
This will modify the local variable trust, and then the function will end. When the function ends, the life-time of the local variable trust also ends, and the modifications you made to it will be lost.
If you truly want to modify the argument, you need to either pass it by reference:
void editPlayer::addTrust(double& trust) {
trust += 5;
}
Or return the new value:
double editPlayer::addTrust(double trust) {
return trust + 5;
}
If you return the new value, you need to assign to it when calling the function:
trust = user.addTrust(trust);
With the above said, the code and the editPlayer class doesn't make much sense. There's just no need for a class editUser really. Possibly addTrust could be a non-member function, or maybe not a function at all.
The class name doesn't make sense, since it doesn't "edit" anything. And passing an argument to the constructor also doesn't make sense since the objects doesn't have any internal state (the value passed to the constructor is just discarded).
Currently you're not storing anything specific on behalf of user object (an object of the editPlayer class.
The cout << trust; statement just prints a value of the trust local variable which you declared at the beginning: double trust=100;. Because this variable hasn't been changed anyhow since that initialization it is still equal to 100 and this is what you see.
In order to track any editPlayer-specific information the best idea is to store that information as a data member of the class editPlayer. You can declare a data member representing the trust of an object like this:
class editPlayer{
public:
editPlayer(double trust);
void addTrust(double);
void removeTrust(double);
double getTrust() const; // add also this one, will be useful
private:
double m_trust {0}; // <---- here - a data member, aka. a class field
};
Now you must refine you constructor to let it utilize the parameter which it takes and assign its value to this new data member (because currently the constructor does nothing):
editPlayer::editPlayer(double trust) {
m_trust = trust;
}
Now in the member functions that you already have just rename the variable so that it reflects the trust data member (and not the parameter) which effectively will allow to update its value:
void editPlayer::addTrust(double trust) {
m_trust += 5;
}
void editPlayer::removeTrust(double trust) {
m_trust -= 5;
}
double editPlayer::getTrust() const { // add definition of our "getter"
return m_trust;
}
Finally you can replace that cout << trust; which we already discussed (still prints the local variable's value) with an invokation of the getter which yields m_trust's value:
cout << user.getTrust();
and see the actual effect of performing the addTrust() operation as well as get delighted with your legitimate object-oriented program.
In general the code you are asking can be covered by classes, member declarations and also a pinch of object oriented programming.
The internet has lots of good (and less than good) tutorials if you search for it.
I would try my luck with some of the following searches
CPP + classes
CPP + member declarations
CPP + dynamic vs. static memory allocation (pointers and stuff)
object oriented programming (OOP)
The examples on this site provide good (and short :D) examples of alot of basic concepts imho.
https://www.tutorialspoint.com/cplusplus/cpp_classes_objects.htm
Some of the topics also apply to other languages.
The first block with my comments:
#include "function.h"
using namespace std; // dont get into the habbit of using namespace std;
// the above can potentially open up for bugs
int main()
{
double trust=100; // This variable is declared in this scope({ ... })
// and will get deallocated once the scope ends with the character '}'
editPlayer user(100); // instance of editPlayer named 'user' is constructed
//asks user choice
cin >> firstChoice;
if (firstChoice == 1) {
user.addTrust(trust); // calling function on user object
cout << trust;
}
Now looking at the .h file i would advocate against including headers that you dont use in the header.
For small projects it does not matter at all - but for big projects of thousands lines of code removing unused includes can speed up things.
Some would prefer forward declarations - which you can look into once you are more comfortable with the basics of cpp.
#include<iostream> // not used here
#include<string> // not used
using namespace std; // disaster waiting to happen
class editPlayer{
public:
editPlayer(double trust);
void addTrust(double);
void removeTrust(double);
};
The .cpp file
#include "function.h"
editPlayer::editPlayer(double trust) {}
// function implementation with argument - but argument is not used - change to void fun(double) -> fun(void) OR fun()
void editPlayer::addTrust(double trust) { trust +=5; }
void editPlayer::removeTrust(double trust) { trust -=5; }
I did an example with class declaration and member variables.
#include <iostream>
#include <string>
// this is a class declaration
class Player
{
protected: // protected member variables
double _trust;
public: // public interface
Player(double trust);
void addTrust(double);
void removeTrust(double);
double getTrust() const;
};
// Implementation of public interface
// notice _trust is the member defined in the class
Player::Player(double trust) : _trust(trust) {} // constructor
// example of default parameters (do note that only definition or declaration can have them)
// This means that calling the function without arguments will become 5
void Player::addTrust(double trust = 5) { _trust += trust; }
void Player::removeTrust(double trust = 5) { _trust -= trust; }
double Player::getTrust() const {return _trust; }
int main()
{
Player player(100); // this will invoke the constructor - and the player object will get initialised with the given state
std::cout << player.getTrust() << std::endl;
// variable to buffer input data into - assuming type int wrt. following if
int firstChoice;
//asks user choice
std::cin >> firstChoice;
if (firstChoice == 1)
{
player.addTrust(25);
player.addTrust();
}
std::cout << player.getTrust();
}
Happy coding !
I am new to C++ and get confused about what goes on under the hood when a class method returns a reference to a member variable that is raw data (rather than a pointer or a reference). Here's an example:
#include <iostream>
using namespace std;
struct Dog {
int age;
};
class Wrapper {
public:
Dog myDog;
Dog& operator*() { return myDog; }
Dog* operator->() { return &myDog; }
};
int main() {
auto w = Wrapper();
// Method 1
w.myDog.age = 1;
cout << w.myDog.age << "\n";
// Method 2
(*w).age = 2;
cout << w.myDog.age << "\n";
// Method 3
w->age = 3;
cout << w.myDog.age << "\n";
}
My question is: what happens at runtime when the code reads (*w) or w-> (as in the main function)? Does it compute the address of the myDog field every time it sees (*it) or it->? Is there overhead to either of these two access methods compared to accessing myDog_ directly?
Thanks!
Technically, what you are asking is entirely system/compiler-specific. As a practicable matter, a pointer and a reference are identical in implementation.
No rational compiler is going to treat
(*x).y
and
x->y
differently. Under the covers both usually appears in assembly language as something like
y(Rn)
Where Rn is a register holding the address of x and y is the offset of y into the structure.
The problem is that C++ is built upon C which in turn is the most f*&*) *p programming language ever devised. The reference construct is a work around to C's inept method of passing parameters.
My IDE is Microsoft Visual Studio 2017.
This is primitive example code:
main.cpp
#include <iostream>
#include "Klasa_00.h"
using namespace std;
int main() {
int const Number_0 = 234;
float const Number_1 = 34.76;
double const Number_2 = 98.78;
cout << "Number_0 is:" << Number_0 << endl;
cout << "Number_1 is:" << Number_0 << endl;
cout << "Number_2 is:" << Number_0 << endl;
system("Pause");
return 0;
}
Klasa_0.cpp
#include "Klasa_00.h"
Klasa_00::Klasa_00()
{
}
Klasa_00::~Klasa_00()
{
}
Klasa_0.h file
#pragma once
class Klasa_00
{
public:
Klasa_00();
~Klasa_00();
};
I am new in C++ programing so I need a help about making code. For example, in Fortran programing language all variables with parameter attribute can be declared in separate module which can be easily used in main program.
What I want to learn here is possibility of using that principle of coding in C++ or something similar.
So, in my case a have a three variables which i want to move into class Klasa_00.
Is there way or ways for doing that?
As others have said, you might want to avoid using classes to store your constants in other files, and you might simply wish to store them in a header (possibly with a namespace, more on that later). Having said that, I do understand that you might want a constant that belongs to a class, so I'll cover that case as well later in the answer.
The simplest way is to declare and define the constant in a header on its own as such:
// YourHeader.h
#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H
[...]
const int aConstNumber = 1;
static const int anotherConstNumber = 2;
constexpr int aConstExprNumber = 3;
static constexpr int anotherConstExprNumber = 4;
[...]
#endif
// main.cpp
#include <iostream>
#include "YourHeader.h"
int main()
{
// You can simply access the variables by name as so:
std::cout << aConstNumber << "\n"; // 1
std::cout << anotherConstNumber << "\n"; // 2
std::cout << aConstExprNumber << "\n"; // 3
std::cout << anotherConstExprNumber << std::endl; // 4
}
These variables all behave the same logically, but they work in different ways. A variable declared with the const keyword is defined at runtime, and guaranties it won't change. A variable declared with the constexpr keyword, however, is defined at compile time.
So, while this means that if you had multiple classes with something like an ID (which shouldn't change, but should be unique), you'd prefer const over constexpr (since the latter wouldn't work in that context).
Let's talk about static as well. static means that there is a single shared instance of that variable across your classes. So if the Bar class has a static int ID value, all instances of Bar share the same ID value. Changing it once changes it for all instances. Though if it's a constant, you won't be able to change it.
In your case, if it's to define constants that are pre-defined and won't change, I'd strongly recommend using constexpr, since you can use those variables to do things you couldn't use a const variable for (like defining the size of an array).
Before you go ahead and do that, however, consider the following class.
class Foo
{
public:
const int a = 5; // Valid use of const.
constexpr int b = 7; // Invalid use of constexpr, won't even compile!
static constexpr int c = 10; // Valid use of constexpr.
int arrA[a]; // ERROR: 'a' is defined at runtime, so you can't use it to define a size.
int arrB[b]; // ERROR: You couldn't even define 'b', so this is not going to work...
int arrC[c]; // VALID: 'c' is known by the compiler, and is guaranteed to only ever be 10!
}
It is worth noting that if you wanted to access a or c (the only two valid variables declared and defined in your class), you'd have to use the following syntax, rather than just their names:
// "Foo" is their class' name, and represents their parent namespace.
std::cout << Foo::a << "\n"; // 5
std::cout << Foo::c << std::endl; // 10
As you can see, constexpr int b = 7; is invalid. Why though? Shouldn't it be seen by the compiler and work just fine? Well, no. You see, the issue is that maybe you'll never instantiate that class, right? const variables are fine, because they're defined at runtime, this means they don't have to exist, they just can't change once you've given them a value. constexpr on the other hand needs to be sure it'll exist, because it has to exist and be valid at compile time!
While declaring a constexpr variable is perfectly fine in a header file, it doesn't work unless you use the static keyword with it if you want to declare one in a class! Because the static keyword will let the compiler know that, regardless of how you instantiate this class, the variable's value will never change and it will be known at compile time thanks to constexpr!
I strongly recommend you read this post to understand just what static and constexpr do when combined.
If you have "constants" that are only constant once instantiated, go with const.
If you have constants that will never change and will always represent the same value (think of mathematical values like PI) go with constexpr.
If all instances of a class should share a constant value, I'd recommend against using static const, since it would be defined at runtime, but it will always have the same value, right? Just use static constexpr instead.
Finally, I mentioned namespaces at the start of this answer. Sometimes, you might want a group of associated constants that don't necessarily belong to a class. For instance, while PI is used in circles, it doesn't necessarily mean that I want to include the circle class' header every time I want PI. But I don't want to have a "raw" PI variable name in my project's namespace! That's just asking for trouble. Instead, consider surrounding your constants in a namespace block to emulate the syntax used to call a class' member!
// YourHeader.h
#ifndef YOUR_HEADER_H
#define YOUR_HEADER_H
namespace MyConstants
{
constexpr int a = 1;
constexpr int b = 2;
}
#endif
// main.cpp
#include <iostream>
#include "YourHeader.h"
int main()
{
std::cout << MyConstants::a << "\n"; // 1
std::cout << MyConstants::b << "\n"; // 2
}
Note that we didn't use static with a namespace, we don't need to since we're not using a class or struct, we're simply wrapping them in the namespace to avoid naming conflicts. static would do something else here. See this post for more info on that.
Extra Note: While it is possible to declare a variable as a constexpr const, I wouldn't recommend it as it does the same as simply declaring it constexpr. Do note that constexpr when combined with pointers will turn the pointer into a constant pointer to a constant value! See this post for more details on that.
Why do you feel that you need a class for this? That doesn't seem appropriate. FORTRAN comparisons are also not likely to bear much fruit as C++ is a different language with different idioms and concepts.
To me, it seems like you should simply put those constants in a header file. Be sure to make them static const constexpr to avoid linker clashes.
// Constants.hpp
#ifndef MYLIB_CONSTANTS_HPP
#define MYLIB_CONSTANTS_HPP
#pragma once
static constexpr const int Number_0 = 234;
static constexpr const float Number_1 = 34.76;
static constexpr const double Number_2 = 98.78;
#endif
Now you just #include "Constants.hpp" in any translation unit that requires access to these values.
For the record, the old-school C approach to do the same thing would be to use #defines.
Don't forget to give these constants meaningful names.
Let's look at the following C++ code:
#include <iostream>
int main()
{
int z = 2;
class A {
public:
const int & x;
A(const int & x) : x(x) {}
void show(){
std::cout << "x=" << this->x << std::endl ;
}
} a(z);
a.show();
z = 3;
a.show();
}
The program prints: 2 and 3
It clearly shows that while inside class A x can't be modified, it merely means it's read only, because I can change it's value from outside.
Of course I can make it a copy stored inside class A, but I'm wondering if there is (or if there is a proposal?) of a way to say to class A that the member x will be truly constant instead of merely read only, with the meaning of a promise that the external code won't change it ?
To my eyes it looks like something related to the meaning of the C restrict keyword, but I've not heard of any such C++ feature yet. Do you ?
Constness is an attribute of the actual variable.
The term const int& x simply means "x is a reference to an int which it will not modify" and of course the compiler enforces this.
If you want the actual variable to which x refers to be const, simply declare it so:
#include <iostream>
int main()
{
const int z = 2; // declared const. Nothing may ever modify it
class A {
public:
const int & x;
A(const int & x) : x(x) {}
void show(){
std::cout << "x=" << this->x << std::endl ;
}
} a(z);
a.show();
z = 3; // this is a logic error, caught by the compiler.
a.show();
}
compiling correctly produces the error:
./const.cpp:41:7: error: read-only variable is not assignable
z = 3;
~ ^
1 error generated.
You're looking for D's immutable keyword, which was introduced as a new concept in that language precisely because, unfortunately, the answer is no: it does not exist in C++.
Constness in C++ does not mean immutability, but that the variable in question is read-only. It can still be modified by other parts of the program. I understand your question as to whether it's possible to enforce true immutability in a called function without knowing what the caller is doing.
Of course you can create a template wrapper class which accomplishes the task:
template <typename T>
class Immutable
{
public:
template <typename ...Args>
Immutable( Args&&...args )
: x( std::forward<Args>(args)... )
{}
operator const T &() const
{
return x;
}
private:
const T x;
};
As long as you do not reinterpret_cast or const_cast you will have truly immutable objects when you wrap them with Immutable<T>.
However, if you have a constant reference to some object, there is no way to tell, if some other part of the program has a non-constant access to the object. In fact, the underlying object might be a global or static variable, that you have read-only access to, but functions you call might still modify it.
This cannot happen with Immutable<T> object. However, using Immutable<T> might impose an extra copy operation on you. You need to judge yourself if you can live with that and if the cost justifies the gain.
Having a function require an const Immutable<Something> & instead of const Something & as an argument affects the calling code. A copy operation might be triggered. Alternatively, you can ask for an Immutable<Something> & without the const. Then no accidental copies will be triggered, but the calling code must pass a reference to Immutable<Something> object. And rightly so, because if the caller received a const & as an argument then the caller does not know, whether the object might get modified by someone else in the program. The caller has to create the object itself or require an immutable object to be passed to it as a reference.
Your original question
Here's your original problem with Immutable<int> & instead of const int &.
#include <iostream>
int main()
{
Immutable<int> z = 2;
class A {
public:
const Immutable<int> & x;
A(Immutable<int> & x) : x(x) {}
void show(){
std::cout << "x=" << this->x << std::endl ;
}
} a(z);
a.show();
//z = 3; // this would fail
a.show();
}
An other example
Here's how it works: If you write
void printAndIncrementAndPrint( int & i1, const int & i2 )
{
std::cout << i2 << std::endl;
++i1;
std::cout << i2 << std::endl;
}
int main()
{
int i = 0;
printAndIncrementAndPrint( i, i );
}
then it will print
0
1
into the console. If you replace the second argument of printAndIncrementAndPrint() with const Immutable<int> & i2 and keep the rest the same, then a copy will be triggered and it will print
0
0
to the console. You cannot pass and Immutable<int> to the function and a int & to the same underlying data without breaking the typesystem using const_cast or reinterpret_cast.
I think this is a design problem for the programmers, not the language. A const variable means for any user of that variable, they should not change the value of that variable. Our compiler is smart enough to help us make sure of that. So A is a user of z and if you want A know that A::x references to a const variable, then you should make z a const int. The const reference is just to keep the contract between the user and the provider.
When declaring and using static const integrals, I find it convenient and natural to use the object reference I'm working with to access the variable, rather than fully-qualifying it with the class name. I'm wondering if there is a downside to this? Take for example:
class MyLongClassNameIdRatherNotHaveEverywhere {
public:
static const int Len = 6;
//...
void otherInterestingThings();
void someWorkToDo();
};
int main() {
MyLongClassNameIdRatherNotHaveEverywhere *lcn = new MyLongClassNameIdRatherNotHaveEverywhere;
lcn->someWorkToDo();
cout << "the length is: " << lcn->Len << endl;
delete lcn;
return 0;
}
Notice the lcn->Len... it's really a constant, and in fact if lcn were null, lcn->Len would still compile and run just fine. I could have written MyLongClassNameIdRatherNotHaveEverywhere::Len there instead, which certainly makes it more obvious (to me at least) that this is a constant. Are there other drawbacks?
Apart from weirdness, I can see a drawback in case operator -> is overloaded...
Scope resolution operator :: btw, cannot be overloaded.