Changing a Permanent Object

I was looking through interview questions for a junior C ++ developer position. Question (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 in accordance with the C ++ 03 and C ++ 11 standards and will be successfully compiled. But it can cause undefined behavior during assignment pointer-> i = 0; if the instance of the class foo () is called on is declared as const .

I mean that the following code will compile successfully and lead to undefined behavior.

 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; } 

Do I believe my answer or is something missing? Thanks.

+6
source share
3 answers

First I will ask what is meant by their ambiguous definition of "correct." You need to know the specification of the program and its intended behavior .

As you said, if they just ask if he compiles, then the answer is yes. However, if they determine the correctness to be safe, then you can discuss the facts that you state in your question.

Responding in this way, the interview can see how you analyze what you are being asked about, instead of just jumping right in the answer, which, in my opinion, is a good thing.

+5
source

This code may be legally correct, but I think the purpose of the question is to determine whether you understand the concept of const itself. Since at the semantic level you have a function that uses an implicit pointer to a const object, which then proceeds to the modification, which is almost certainly a mistake.

There are cases where this may be desirable (since the modification is some caching of the return values ​​or a similar operation that does not change the semantic value of the object), you should use the mutable keyword for the variable in question.

+1
source

the deceiver will accept 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; } 

the program will crack when "const Foo & tmp = ite-> first;"

0
source

Source: https://habr.com/ru/post/950181/


All Articles