I was looking through the interview questions to a junior C++ developer position. The question is (quote):
Is the following code correct?
struct Foo
{
int i;
void foo ( void ) const
{
Foo* pointer = const_cast<Foo*>(this);
pointer->i = 0;
}
};
I would answer:
The code itself is valid according to the C++03 and c++11 standards and will compile successfully.
But it may invoke an undefined behavior during assignment pointer->i
= 0; if the instance of the class on which foo() is being called is declared as const.
I mean that following code will compile successfully and result in undefined behaviour.
struct Foo
{
int i;
Foo ( void )
{
}
void foo ( void ) const
{
Foo* pointer = const_cast<Foo*>(this);
pointer->i = 0;
}
};
int main ( void )
{
Foo foo1;
foo1.foo(); // Ok
const Foo foo2;
foo2.foo(); // UB
return 0;
}
Is my answer correct or I am missing something? Thank you.
I would first ask what is meant by their ambiguous definition of "correct". You need to know the specification of the program and its intended behaviour.
As you said, if they're just asking if it compiles then the answer is 'yes'. However, if they determine correct to be safe to do, then you can discuss the facts that you state in your question.
By answering this way, the person interviewing can see how that you're analysing what you're being asked, rather than jumping straight into answering, which in my opinion is a good thing to do.
This code may be legally correct, but I guess, the aim of the question is to determine, whether you understood the concept of const itself. Because, on the semantic level, you have a function taking an implicit const object pointer, which it then goes to modify, which is almost certainly a bug.
There are cases, where this may be desired (because the modification is some caching of return values, or similar operation that does not change the semantic value of the object), you would use the mutable keyword for the variable in question.
cheating complier will take the consequences.
struct Foo
{
int i;
Foo(int a):i(a){}
void foo ( void ) const
{
Foo* pointer = const_cast<Foo*>(this);
pointer->i = 0;
}
bool operator<(const Foo& rhs) const{
return i<rhs.i;
}
};
#include <map>
int main ( void )
{
std::map<Foo,int> kk;
for(int i=0;i<10;++i){
kk.insert(std::make_pair(Foo(i),i));
}
std::map<Foo,int>::iterator ite = kk.find(Foo(4));
const Foo& foo4 = ite->first;
foo4.foo();
ite = kk.find(Foo(4));
const Foo& tmp = ite->first; // crack
return 0;
}
program will crack at "const Foo& tmp = ite->first;"
Related
This question already has answers here:
How do I remove code duplication between similar const and non-const member functions?
(21 answers)
C++ template to cover const and non-const method
(7 answers)
Closed 5 years ago.
Is there any advantage using one over the other:
class Foo
{
public:
const int& get() const
{
// stuff here
return myInt;
}
int& get()
{
return const_cast<int&>(static_cast<const Foo*>(this)->get());
}
};
Or
class Foo
{
public:
int& get()
{
// stuff here
return myInt;
}
const int& get() const
{
return const_cast<Foo*>(this)->get();
}
};
I only used the first one, but I just saw the second one used somewhere, so I am wondering.
The comment // stuff here could be a non-trivial check like retrieving the index of a table in order to return a ref on a member of the table (for example: myInt = myTable[myComputedIndex];) so I cannot just make it public. Thus table and any member are not const.
If you have to make a function that is const-agnostic, and avoids duplication, one neat way to do it is delegating implementation to a template, for example
class Foo {
private:
int my_int;
template <typename ThisPtr>
static auto& get(ThisPtr this_ptr) {
return this_ptr->my_int;
}
public:
int& get() {
return get(this);
}
const int& get() const {
return get(this);
}
};
This way you are free from the fear associated with using const_cast, mutable and other stuff that goes into trying to reduce code duplication in cases like this. If you get something wrong, the compiler will let you know.
Ignoring the issue of whether you really need a getter, the best solution when duplicating functionality in both a const and non-const method is to have the non-const method call the const method and cast away the const-ness of the result (i.e. the first of the two alternatives you present in the question).
The reason is simple: if you do it the other way around (with the logic in the non-const method), you could accidentally end up modifying a const object, and the compiler won't catch it at compile time (because the method is not declared const) - this will have undefined behaviour.
Of course this is only a problem if the "getter" is not actually a getter (i.e. if it is doing something more complicated than just returning a reference to a private field).
Also, if you are not constrained to C++11, the template-based solution presented by Curious in their answer is another way of avoiding this problem.
Is there any advantage using one over the other: ...
No, both are bad because they violate the data encapsulation principle.
In your example you should rather make myInt a public member.
There's no advantage to have getters for such case at all.
If you really want (need) getter and setter functions these should look like this:
class Foo
{
private:
mutable int myInt_;
// ^^^^^^^ Allows lazy initialization from within the const getter,
// simply omit that if you dont need it.
public:
void myInt(int value)
{
// Do other stuff ...
myInt = value;
// Do more stuff ...
}
const int& myInt() const
{
// Do other stuff ...
return myInt_;
}
}
You don't say where myInt comes from, the best answer depends on that.
There are 2+1 possible scenarios:
1) The most common case is that myInt comes from a pointer internal to the class.
Assuming that, this is the best solution which avoids both code duplication and casting.
class Foo{
int* myIntP;
...
int& get_impl() const{
... lots of code
return *myIntP; // even if Foo instance is const, *myInt is not
}
public:
int& get(){return get_impl();}
const int& get() const{return get_impl();}
};
This case above applies to pointer array, and (most) smart pointers.
2) The other common case is that myInt is a reference or a value member, then the previous solution doesn't work.
But it is also the case where a getter is not needed at all.
Don't use a getter in that case.
class Foo{
public:
int myInt; // or int& myInt;
};
done! :)
3) There is a third scenario, pointed by #Aconcagua, that is the case of an internal fixed array. In that case it is a toss-up, it really depends what you are doing, if finding the index is really the problem, then that can be factored away. It is not clear however what is the application:
class Foo{
int myInts[32];
...
int complicated_index() const{...long code...}
public:
int& get(){return myInts[complicated_index()];}
const int& get() const{return myInts[complicated_index()];}
};
My point is, understand the problem and don´t over engineer. const_cast or templates are not needed to solve this problem.
complete working code below:
class Foo{
int* myIntP;
int& get_impl() const{
return *myIntP; // even if Foo instance is const, *myInt is not
}
public:
int& get(){return get_impl();}
const int& get() const{return get_impl();}
Foo() : myIntP(new int(0)){}
~Foo(){delete myIntP;}
};
#include<cassert>
int main(){
Foo f1;
f1.get() = 5;
assert( f1.get() == 5 );
Foo const f2;
// f2.get() = 5; // compile error
assert( f2.get() == 0 );
return 0;
}
As you intend access to more complex internal structures (as clarified via your edit; such as providing an operator[](size_t index) for internal arrays as std::vector does), then you will have to make sure that you do not invoke undefined behaviour by modifying a potentially const object.
The risk of doing so is higher in the second approach:
int& get()
{
// stuff here: if you modify the object, the compiler won't warn you!
// but you will modify a const object, if the other getter is called on one!!!
return myInt;
}
In the first variant, you are safe from (unless you do const_cast here, too, which now would really be bad...), which is the advantage of this approach:
const int& get() const
{
// stuff here: you cannot modify by accident...
// if you try, the compiler will complain about
return myInt;
}
If you actually need to modify the object in the non-const getter, you cannot have a common implementation anyway...
Modifying a const object through a non-const access path [...] results in undefined behavior.
(Source: http://en.cppreference.com/w/cpp/language/const_cast)
This means that the first version can lead to undefined behavior if myInt is actually a const member of Foo:
class Foo
{
int const myInt;
public:
const int& get() const
{
return myInt;
}
int& get()
{
return const_cast<int&>(static_cast<const Foo*>(this)->get());
}
};
int main()
{
Foo f;
f.get() = 10; // this compiles, but it is undefined behavior
}
The second version would not compile, because the non-const version of get would be ill-formed:
class Foo
{
int const myInt;
public:
int& get()
{
return myInt;
// this will not compile, you cannot return a const member
// from a non-const member function
}
const int& get() const
{
return const_cast<Foo*>(this)->get();
}
};
int main()
{
Foo f;
f.get() = 10; // get() is ill-formed, so this does not compile
}
This version is actually recommended by Scott Meyers in Effective C++ under Avoid Duplication in const and Non-const Member Function.
For a class Foo, is there a way to disallow constructing it without giving it a name?
For example:
Foo("hi");
And only allow it if you give it a name, like the following?
Foo my_foo("hi");
The lifetime of the first one is just the statement, and the second one is the enclosing block. In my use case, Foo is measuring the time between constructor and destructor. Since I never refer to the local variable, I often forget to put it in, and accidentally change the lifetime. I'd like to get a compile time error instead.
Another macro-based solution:
#define Foo class Foo
The statement Foo("hi"); expands to class Foo("hi");, which is ill-formed; but Foo a("hi") expands to class Foo a("hi"), which is correct.
This has the advantage that it is both source- and binary-compatible with existing (correct) code. (This claim is not entirely correct - please see Johannes Schaub's Comment and ensuing discussion below: "How can you know that it is source compatible with existing code? His friend includes his header and has void f() { int Foo = 0; } which previously compiled fine and now miscompiles! Also, every line that defines a member function of class Foo fails: void class Foo::bar() {}")
How about a little hack
class Foo
{
public:
Foo (const char*) {}
};
void Foo (float);
int main ()
{
Foo ("hello"); // error
class Foo a("hi"); // OK
return 1;
}
Make the constructor private but give the class a create method.
This one doesn't result in a compiler error, but a runtime error. Instead of measuring a wrong time, you get an exception which may be acceptable too.
Any constructor you want to guard needs a default argument on which set(guard) is called.
struct Guard {
Guard()
:guardflagp()
{ }
~Guard() {
assert(guardflagp && "Forgot to call guard?");
*guardflagp = 0;
}
void *set(Guard const *&guardflag) {
if(guardflagp) {
*guardflagp = 0;
}
guardflagp = &guardflag;
*guardflagp = this;
}
private:
Guard const **guardflagp;
};
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics are:
Foo f() {
// OK (no temporary)
Foo f1("hello");
// may throw (may introduce a temporary on behalf of the compiler)
Foo f2 = "hello";
// may throw (introduces a temporary that may be optimized away
Foo f3 = Foo("hello");
// OK (no temporary)
Foo f4{"hello"};
// OK (no temporary)
Foo f = { "hello" };
// always throws
Foo("hello");
// OK (normal copy)
return f;
// may throw (may introduce a temporary on behalf of the compiler)
return "hello";
// OK (initialized temporary lives longer than its initializers)
return { "hello" };
}
int main() {
// OK (it's f that created the temporary in its body)
f();
// OK (normal copy)
Foo g1(f());
// OK (normal copy)
Foo g2 = f();
}
The case of f2, f3 and the return of "hello" may not be wanted. To prevent throwing, you can allow the source of a copy to be a temporary, by resetting the guard to now guard us instead of the source of the copy. Now you also see why we used the pointers above - it allows us to be flexible.
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
Foo(Foo &&other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
Foo(const Foo& other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics for f2, f3 and for return "hello" are now always // OK.
A few years ago I wrote a patch for the GNU C++ compiler which adds a new warning option for that situation. This is tracked in a Bugzilla item.
Unfortunately, GCC Bugzilla is a burial ground where well-considered patch-included feature suggestions go to die. :)
This was motivated by the desire to catch exactly the sort of bugs that are the subject of this question in code which uses local objects as gadgets for locking and unlocking, measuring execution time and so forth.
As is, with your implementation, you cannot do this, but you can use this rule to your advantage:
Temporary objects cannot be bound to non-const references
You can move the code from the class to an freestanding function which takes a non-const reference parameter. If you do so, You will get a compiler error if an temporary tries to bind to the non-const reference.
Code Sample
class Foo
{
public:
Foo(const char* ){}
friend void InitMethod(Foo& obj);
};
void InitMethod(Foo& obj){}
int main()
{
Foo myVar("InitMe");
InitMethod(myVar); //Works
InitMethod("InitMe"); //Does not work
return 0;
}
Output
prog.cpp: In function ‘int main()’:
prog.cpp:13: error: invalid initialization of non-const reference of type ‘Foo&’ from a temporary of type ‘const char*’
prog.cpp:7: error: in passing argument 1 of ‘void InitMethod(Foo&)’
Simply don't have a default constructor, and do require a reference to an instance in every constructor.
#include <iostream>
using namespace std;
enum SelfRef { selfRef };
struct S
{
S( SelfRef, S const & ) {}
};
int main()
{
S a( selfRef, a );
}
No, I'm afraid this isn't possible. But you could get the same effect by creating a macro.
#define FOO(x) Foo _foo(x)
With this in place, you can just write FOO(x) instead of Foo my_foo(x).
Since the primary goal is to prevent bugs, consider this:
struct Foo
{
Foo( const char* ) { /* ... */ }
};
enum { Foo };
int main()
{
struct Foo foo( "hi" ); // OK
struct Foo( "hi" ); // fail
Foo foo( "hi" ); // fail
Foo( "hi" ); // fail
}
That way you can't forget to name the variable and you can't forget to write struct. Verbose, but safe.
Declare one-parametric constructor as explicit and nobody will ever create an object of that class unintentionally.
For example
class Foo
{
public:
explicit Foo(const char*);
};
void fun(const Foo&);
can only be used this way
void g() {
Foo a("text");
fun(a);
}
but never this way (through a temporary on the stack)
void g() {
fun("text");
}
See also: Alexandrescu, C++ Coding Standards, Item 40.
For a class Foo, is there a way to disallow constructing it without giving it a name?
For example:
Foo("hi");
And only allow it if you give it a name, like the following?
Foo my_foo("hi");
The lifetime of the first one is just the statement, and the second one is the enclosing block. In my use case, Foo is measuring the time between constructor and destructor. Since I never refer to the local variable, I often forget to put it in, and accidentally change the lifetime. I'd like to get a compile time error instead.
Another macro-based solution:
#define Foo class Foo
The statement Foo("hi"); expands to class Foo("hi");, which is ill-formed; but Foo a("hi") expands to class Foo a("hi"), which is correct.
This has the advantage that it is both source- and binary-compatible with existing (correct) code. (This claim is not entirely correct - please see Johannes Schaub's Comment and ensuing discussion below: "How can you know that it is source compatible with existing code? His friend includes his header and has void f() { int Foo = 0; } which previously compiled fine and now miscompiles! Also, every line that defines a member function of class Foo fails: void class Foo::bar() {}")
How about a little hack
class Foo
{
public:
Foo (const char*) {}
};
void Foo (float);
int main ()
{
Foo ("hello"); // error
class Foo a("hi"); // OK
return 1;
}
Make the constructor private but give the class a create method.
This one doesn't result in a compiler error, but a runtime error. Instead of measuring a wrong time, you get an exception which may be acceptable too.
Any constructor you want to guard needs a default argument on which set(guard) is called.
struct Guard {
Guard()
:guardflagp()
{ }
~Guard() {
assert(guardflagp && "Forgot to call guard?");
*guardflagp = 0;
}
void *set(Guard const *&guardflag) {
if(guardflagp) {
*guardflagp = 0;
}
guardflagp = &guardflag;
*guardflagp = this;
}
private:
Guard const **guardflagp;
};
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics are:
Foo f() {
// OK (no temporary)
Foo f1("hello");
// may throw (may introduce a temporary on behalf of the compiler)
Foo f2 = "hello";
// may throw (introduces a temporary that may be optimized away
Foo f3 = Foo("hello");
// OK (no temporary)
Foo f4{"hello"};
// OK (no temporary)
Foo f = { "hello" };
// always throws
Foo("hello");
// OK (normal copy)
return f;
// may throw (may introduce a temporary on behalf of the compiler)
return "hello";
// OK (initialized temporary lives longer than its initializers)
return { "hello" };
}
int main() {
// OK (it's f that created the temporary in its body)
f();
// OK (normal copy)
Foo g1(f());
// OK (normal copy)
Foo g2 = f();
}
The case of f2, f3 and the return of "hello" may not be wanted. To prevent throwing, you can allow the source of a copy to be a temporary, by resetting the guard to now guard us instead of the source of the copy. Now you also see why we used the pointers above - it allows us to be flexible.
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
Foo(Foo &&other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
Foo(const Foo& other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics for f2, f3 and for return "hello" are now always // OK.
A few years ago I wrote a patch for the GNU C++ compiler which adds a new warning option for that situation. This is tracked in a Bugzilla item.
Unfortunately, GCC Bugzilla is a burial ground where well-considered patch-included feature suggestions go to die. :)
This was motivated by the desire to catch exactly the sort of bugs that are the subject of this question in code which uses local objects as gadgets for locking and unlocking, measuring execution time and so forth.
As is, with your implementation, you cannot do this, but you can use this rule to your advantage:
Temporary objects cannot be bound to non-const references
You can move the code from the class to an freestanding function which takes a non-const reference parameter. If you do so, You will get a compiler error if an temporary tries to bind to the non-const reference.
Code Sample
class Foo
{
public:
Foo(const char* ){}
friend void InitMethod(Foo& obj);
};
void InitMethod(Foo& obj){}
int main()
{
Foo myVar("InitMe");
InitMethod(myVar); //Works
InitMethod("InitMe"); //Does not work
return 0;
}
Output
prog.cpp: In function ‘int main()’:
prog.cpp:13: error: invalid initialization of non-const reference of type ‘Foo&’ from a temporary of type ‘const char*’
prog.cpp:7: error: in passing argument 1 of ‘void InitMethod(Foo&)’
Simply don't have a default constructor, and do require a reference to an instance in every constructor.
#include <iostream>
using namespace std;
enum SelfRef { selfRef };
struct S
{
S( SelfRef, S const & ) {}
};
int main()
{
S a( selfRef, a );
}
No, I'm afraid this isn't possible. But you could get the same effect by creating a macro.
#define FOO(x) Foo _foo(x)
With this in place, you can just write FOO(x) instead of Foo my_foo(x).
Since the primary goal is to prevent bugs, consider this:
struct Foo
{
Foo( const char* ) { /* ... */ }
};
enum { Foo };
int main()
{
struct Foo foo( "hi" ); // OK
struct Foo( "hi" ); // fail
Foo foo( "hi" ); // fail
Foo( "hi" ); // fail
}
That way you can't forget to name the variable and you can't forget to write struct. Verbose, but safe.
Declare one-parametric constructor as explicit and nobody will ever create an object of that class unintentionally.
For example
class Foo
{
public:
explicit Foo(const char*);
};
void fun(const Foo&);
can only be used this way
void g() {
Foo a("text");
fun(a);
}
but never this way (through a temporary on the stack)
void g() {
fun("text");
}
See also: Alexandrescu, C++ Coding Standards, Item 40.
The following code
#include <vector>
#include <string>
#include <iostream>
std::string const& at(std::vector<std::string> const& n, int i)
{
return n[i];
}
std::vector<std::string> mkvec()
{
std::vector<std::string> n;
n.push_back("kagami");
n.push_back("misao");
return n;
}
int main()
{
std::string const& s = at(mkvec(), 0);
std::cout << s << std::endl; // D'oh!
return 0;
}
may lead to crash because the original vector is already destructed there. In C++ 2011 (c++0x) after rvalue-reference is introduced in, a deleted function declaration can be used to completely forbid calls to at if the vector argument is an rvalue
std::string const& at(std::vector<std::string>&&, int) = delete;
That looks good, but the following code still cause crash
int main()
{
std::string const& s = mkvec()[0];
std::cout << s << std::endl; // D'oh!
return 0;
}
because calls to member function operator [] (size_type) const of an rvalue object is still allowed. Is there any way can I forbid this kind of calls?
FIX:
The examples above is not what I did in real projects. I just wonder if C++ 2011 support any member function qualifying like
class A {
void func() rvalue; // Then a call on an rvalue object goes to this overload
void func() const;
};
FIX:
It's great, but I think C++ standard goes too far at this feature. Anyway, I have following code compiled on clang++ 2.9
#include <cstdio>
struct A {
A() {}
void func() &
{
puts("a");
}
void func() &&
{
puts("b");
}
void func() const &
{
puts("c");
}
};
int main()
{
A().func();
A a;
a.func();
A const b;
b.func();
return 0;
}
Thanks a lot!
No, and you shouldn't. How am I to do std::cout << at(mkvec(), 0) << std::endl;, a perfectly reasonable thing, if you've banned me from using at() on temporaries?
Storing references to temporaries is just a problem C++ programmers have to deal with, unfortunately.
To answer your new question, yes, you can do this:
class A {
void func() &; // lvalues go to this one
void func() &&; // rvalues go to this one
};
A a;
a.func(); // first overload
A().func(); // second overload
Just an idea:
To disable copying constructor on the vector somehow.
vector ( const vector<T,Allocator>& x );
Implicit copying of arrays is not that good thing anyway. (wondering why STL authors decided to define such ctor at all)
It will fix problems like you've mentioned and as a bonus will force you to use more effective version of your function:
void mkvec(std::vector<std::string>& n)
{
n.push_back("kagami");
n.push_back("misao");
}
I'm having this problem with C++ classes. I would like to get pointer to myBar object and store it in quxBar. The reason is I would like to be able to check the value using quxBar->getX() but I would also like to prevent from accidentally modyfing it from Qux so I tried using Bar const*.
class Bar
{
private:
int x;
public:
void setX(int X) { x = X; };
int getX(){ return x };
}
class Foo
{
private:
Bar *myBar;
public:
Bar const* getPointerToBar(){ return myBar; };
}
class Qux
{
void myMethod();
Bar const* quxBar;
Foo *mainFoo;
}
void Qux::myMethod()
{
quxBar = mainFoo->getPointerToBar();
std::cout << quxBar->getX();
quxBar->setX(100); // HERE!!!
std::cout << quxBar->getX(); // returns 100
}
Unfortunatelly it doesn't work since I'm still able to perform quxBar->setX(100) with no compilation error.
Probably my approach is totally wrong, but using current "skills" :) I have no idea how to fix it.
Thanks in advance for any help and suggestions.
I don't think this is your actual code, firstly due to the syntax errors it has, and secondly due to the fact that it actually is correct (mostly). More specifically, with this piece of code, quxBar->setX(100); would result in compilation error.
However, quxBar->getX() would also be a compilation error, you need to tell the compiler that can be called on const objects, you do this by adding const at the end of the function signature:
int getX() const { return x; }
Perhaps in your actual code you had Bar* const quxBar instead of Bar const* quxBar; they mean two different things: The former is a const pointer to Bar, while the later is a pointer to const Bar. Eg. in the earlier case, only the pointer itself can't be modified, but the object it points to can.