I have some questions about the internal workings of C++. I know for example that every member function of a class has an implied hidden parameter, which is the this-pointer (much in the same way Python does):
class Foo
{
Foo(const Foo& other);
};
// ... is actually...
class Foo
{
Foo(Foo* this, const Foo& other);
};
Is it wrong of me to then assume then that the validity of the function does not directly depend on the validity of this (since it's just another parameter)? I mean, sure, if you try to access a member of the this-pointer, it better be valid, but the function will otherwise continue if this is deleted, right?
For example, what if I were to mess up with the this pointer and do something like what you see below? Is this undefined behavior, or is it defined by highly discouraged? (I'm asking out of pure curiosity.)
Foo:Foo(const Foo& other)
{
delete this;
this = &other;
}
You cannot assign to this - it is of type Foo * const. You can delete this; in certain circumstances, but it's rarely a good idea.
this is defined as,
Foo(Foo* const this, ...);
Casting away the constness is not not possible for this (special case). Compiler will give errors for the same. I have asked the similar question.
Related
Minimal question
Please consider the following functions:
class NonTrivialClass { /* ... */ };
void f1(NonTrivialClass &) {}
void f2(NonTrivialClass const&) {}
Is there an expression invoking f1 in which one could not replace f1 with f2?
Context
In the prospect of a job offering, I've been asked "to write the method double approx(vector<Point>& pts)" (Point being given) which uses points from pts to approximate a known constant in a Buffon-like way.
I have written an implementation defining double approx(vector<Point> const& pts) (note the const). And for a reason yet to determine, I've failed the test!
After removing all possible explanation, I'm left with doubts about the test platform and that gripping const qualifier... Is it possible that their test program would have worked with double approx(vector<Point>& pts) but not with double approx(vector<Point> const& pts)?
If your question admits insane answers:
struct NonTrivialClass {};
struct NonTrivialClass2 {
operator NonTrivialClass&();
operator NonTrivialClass const&();
};
void f1(NonTrivialClass &) {}
void f2(NonTrivialClass const&) {}
int main()
{
NonTrivialClass2 foo;
f1(foo);
f2(foo); // error: reference initialization is ambiguous
}
of course, this doesn't apply to the vector<> case (unless the test machinery passes some kind of 'tester' object with a broken (maybe templated, sfinae-unfriendly-whatever) converting operator to some wrapped vector member ? seems unreasonable ... but not impossible)
If there was such an expression (apart from such cases where f2 was inaccessible for any reason), that would break my own C++ knowledge entirely...
I consider it much more likely that you implemented a minimal bug (you are not yet aware of) in your function leading to failure; cannot exclude, though, that the test evaluation software is dumb enough just to look for a fix, given signature, no matter if yours is compatible or not...
Let's say that I create a class where the primary use case will have the user always calling methods that modify its members. Or, looking at it another way, creating a class where every method will modify a class member(s).
For example, let's work with this dummy class:
class Foo
{
public:
void setM_1(int);
void setM_2(char);
void setM_3(float);
private:
int m_1;
char m_2;
float m_3;
};
For this Foo class, creating a const instance of it doesn't make sense, since every method is guaranteed to modify a member.
My goal is this: define this class in such a way that const-ly instantiating this class would have no effect. That is to say, a const Foo instance would be able to call every method that a Foo instance can.
I was able to achieve this behavior by marking every method const, declaring all non-const members mutable, and providing a ctor that initialized all members of the class.
So the const-ignorant version of Foo looks like:
class Foo
{
public:
Foo()
{
m_1 = 0;
m_2 = '\0';
m_3 = 0.0f;
}
void setM_1(int) const;
void setM_2(char) const;
void setM_3(float) const;
private:
mutable int m_1;
mutable char m_2;
mutable float m_3;
};
My question is this: is there a more elegant way of doing this?
Or, is this just bad class design? (no debates please).
After Answer Edit:
It's official: I just took a brain crap.
Kerrek SB is right: creating a const Foo and using class-modifying methods would raise compiler errors anyways, so my "const-ignorant" Foo is pointless.
A little documentation would solve my "problem".
No wonder I had a hunch that this was terrible class design.
Excuse me everyone, this question must've been an eyesore. Thank you for the constructive criticism.
Your goal is fundamentally incorrect. const exists not for funsies, but because it means that you really need const. Such a class would break horribly as e.g. a set key- where mutating it would break the ordering. There are other pitfalls like what happens when you provide it as a temporary in certain cases.
If your class cannot be realistically used in a const way, the interface should not lie about it and pretend that it's const when it isn't.
As for your question about bad design, I can safely say that yes, this sounds like a truly terrible design.
No, thank frak.
This makes no sense and would be extremely confusing/dangerous.
If you don't think it makes sense to have a const T then don't instantiate a const T.
From a language point of view, what bad things will happen if a class cannot be const:
First of all, is it that declaring an L-value of type const for it is not allowed, or that const references to it are also prohibited?
If you do not have const reference, then you won't have the default copy constructor, or copy assignment operator. You can't have the class be a member of any other class either, unless that also cannot be const.
I have seen some (sloppy) code where people implement iterators, and because they get tired of writing boilerplate, they implement const_iterators by const_casting away the const and using the non-const iterator implementation. They do this with classes that they know won't "actually" be const, so it won't be undefined behavior in their program. Potentially, not much fun for maintainers though.
For these classes, the class "cannot be const" in the sense that if you actually created a const one on the stack and used it normally you could technically get UB.
If what you want is for the compiler to complain when someone creates a const instance of some class, I think that doesn't really make sense. Const is fundamentally a "promise not to change something". Why would you want to forbid the programmer from making a promise about how he will use something, that seems only beneficial.
I've ran across a question I am not able to answer for myself. Also, I didn't find an answer to this on both google and here. Say, I want to "check an object for validity" in an if clause, like so:
MyClass myObject;
// [some code, if any]
if (!myObject)
{
// [do something]
}
Let MyClass be defined something like this:
class MyClass
{
public:
MyClass() { };
virtual ~MyClass() { };
bool operator!()
{
return !myBool;
};
operator bool()
{
return myBool;
};
private:
bool myBool = 0;
};
My question now is: Which one of the overloaded operators is actually used in this if clause? Either way, the result is obviously the same.
It will use operator!.
A function whose parameter types match the arguments will be chosen in preference to one that requires type conversions.
You'll find that operator ! gets executed because it's the most direct resolution. If it used operator bool instead then it would have to call the conversion operator first, and then apply the ! separately to that.
As a general rule, it's a good idea to avoid that situation though. It's generally better just to define the bool conversion, because strictly speaking that's what you want your logical operators to act on, rather than MyClass directly. Defining both creates a bit of a readability problem, and is a form of redundant code duplication (which can lead to programmer error in future).
Are there any established patterns for checking class invariants in C++?
Ideally, the invariants would be automatically checked at the beginning and at the end of each public member function. As far as I know, C with classes provided special before and after member functions, but unfortunately, design by contract wasn't quite popular at the time and nobody except Bjarne used that feature, so he removed it.
Of course, manually inserting check_invariants() calls at the beginning and at the end of each public member function is tedious and error-prone. Since RAII is the weapon of choice to deal with exceptions, I came up with the following scheme of defining an invariance checker as the first local variable, and that invariance checker checks the invariants both at construction and destruction time:
template <typename T>
class invariants_checker
{
const T* p;
public:
invariants_checker(const T* p) : p(p)
{
p->check_invariants();
}
~invariants_checker()
{
p->check_invariants();
}
};
void Foo::bar()
{
// class invariants checked by construction of _
invariants_checker<Foo> _(this);
// ... mutate the object
// class invariants checked by destruction of _
}
Question #0: I suppose there is no way to declare an unnamed local variable? :)
We would still have to call check_invariants() manually at the end of the Foo constructor and at the beginning of the Foo destructor. However, many constructor bodies and destructor bodies are empty. In that case, could we use an invariants_checker as the last member?
#include <string>
#include <stdexcept>
class Foo
{
std::string str;
std::string::size_type cached_length;
invariants_checker<Foo> _;
public:
Foo(const std::string& str)
: str(str), cached_length(str.length()), _(this) {}
void check_invariants() const
{
if (str.length() != cached_length)
throw std::logic_error("wrong cached length");
}
// ...
};
Question #1: Is it valid to pass this to the invariants_checker constructor which immediately calls check_invariants via that pointer, even though the Foo object is still under construction?
Question #2: Do you see any other problems with this approach? Can you improve it?
Question #3: Is this approach new or well-known? Are there better solutions available?
Answer #0: You can have unnamed local variables, but you give up control over the life time of the object - and the whole point of the object is because you have a good idea when it goes out of scope. You can use
void Foo::bar()
{
invariants_checker<Foo>(this); // goes out of scope at the semicolon
new invariants_checker<Foo>(this); // the constructed object is never destructed
// ...
}
but neither is what you want.
Answer #1: No, I believe it's not valid. The object referenced by this is only fully constructed (and thus starts to exist) when the constructor finished. You're playing a dangerous game here.
Answer #2 & #3: This approach is not new, a simple google query for e.g. "check invariants C++ template" will yield a lot of hits on this topic. In particular, this solution can be improved further if you don't mind overloading the -> operator, like this:
template <typename T>
class invariants_checker {
public:
class ProxyObject {
public:
ProxyObject(T* x) : m(x) { m->check_invariants(); }
~ProxyObject() { m->check_invariants(); }
T* operator->() { return m; }
const T* operator->() const { return m; }
private:
T* m;
};
invariants_checker(T* x) : m(x) { }
ProxyObject operator->() { return m; }
const ProxyObject operator->() const { return m; }
private:
T* m;
};
The idea is that for the duration of a member function call, you create an anonymous proxy object which performs the check in its constructor and destructor. You can use the above template like this:
void f() {
Foo f;
invariants_checker<Foo> g( &f );
g->bar(); // this constructs and destructs the ProxyObject, which does the checking
}
Ideally, the invariants would be automatically checked at the beginning and at the end of each public member function
I think this is overkill; I instead check invariants judiciously. The data members of your class are private (right?), so only its member functions can change the data memebers and therefore invalidate invariants. So you can get away with checking an invariant just after a change to a data member that particiaptes in that invariant.
Question #0: I suppose there is no way to declare an unnamed local variable? :)
You can usually whip up something using macros and __LINE__, but if you just pick a strange enough name, it should already do, since you shouldn't have more than one (directly) in the same scope. This
class invariants_checker {};
template<class T>
class invariants_checker_impl : public invariants_checker {
public:
invariants_checker_impl(T* that) : that_(that) {that_->check_invariants();}
~invariants_checker_impl() {that_->check_invariants();}
private:
T* that_;
};
template<class T>
inline invariants_checker_impl<T> get_invariant_checker(T* that)
{return invariants_checker_impl<T>(that);}
#define CHECK_INVARIANTS const invariants_checker&
my_fancy_invariants_checker_object_ = get_invariant_checker(this)
works for me.
Question #1: Is it valid to pass this to the invariants_checker constructor which immediately calls check_invariants via that pointer, even though the Foo object is still under construction?
I'm not sure whether it invokes UB technical. In practice it would certainly be safe to do so - where it not for the fact that, in practice, a class member that has to be declared at a specific position in relation to other class members is going to be a problem sooner or later.
Question #2: Do you see any other problems with this approach? Can you improve it?
See #2. Take a moderately sized class, add half a decade of extending and bug-fixing by two dozen developers, and I consider the chances to mess this up at at least once at about 98%.
You can somewhat mitigate this by adding a shouting comment to the data member. Still.
Question #3: Is this approach new or well-known? Are there better solutions available?
I hadn't seen this approach, but given your description of before() and after() I immediately thought of the same solution.
I think Stroustrup had an article many (~15?) years ago, where he described a handle class overloading operator->() to return a proxy. This could then, in its ctor and dtor, perform before- and after-actions while being oblivious to the methods being invoked through it.
Edit: I see that Frerich has added an answer fleshing this out. Of course, unless your class already needs to be used through such a handle, this is a burden onto your class' users. (IOW: It won't work.)
#0: No, but things could be slightly better with a macro (if you're ok with that)
#1: No, but it depends. You cannot do anything that would cause this to be dereferenced in before the body (which yours would, but just before, so it could work). This means that you can store this, but not access fields or virtual functions. Calling check_invariants() is not ok if it's virtual. I think it would work for most implementations, but not guaranteed to work.
#2: I think it will be tedious, and not worth it. This have been my experience with invariant checking. I prefer unit tests.
#3: I've seen it. It seems like the right way to me if you're going to do it.
unit testing is better alternative that leads to smaller code with better performance
I clearly see the issue that your destructor is calling a function that will often throw, that's a no-no in C++ isn't it?
Forgive me my C++ is incredibly rusty. But I am trying to take some old code and recompile it under Visual C++ 2008. It was originally written for Visual C++ 6.0
The error I am getting is this:
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Ok seems simple enough. But then I look at the offending line of code:
operator=(int i) {SetAsInt(i);};
And it appears the type IS declared. So what am I missing?
FOLLOW UP:
I took Micheals advice and added a return type of the function (the class), and added return this; to the end of each. Then I ran across this:
operator=(const CString& str);
There is no function body defined... what exactly does this mean?
You need to have the operator=() method return something (it would assume int if the diagnostic weren't an error, as the error message somewhat confusingly indicates).
Generally it would be a reference to the object the operator is working on so the assignments can be chained as in a normal assignment expression. Something like:
// where T is the class for this operator= implementation
T& operator=( int i) {
// ...
return *this;
}
As michael has said, operator= needs a return type, but this type can be void:
class A {
...
void operator = ( int i ) {
SetAsInt(i);
}
};
although this means you won't be able to "daisy-chain" assignments.
Regarding the follow-up, it's probably saying that assignment for the class is forbidden:
class B {
private:
void operator =( const B & );
};
Making the assignment op (and usually the copy ctor) private and then not implementing them means it is impossible to assign (or copy) class instances, which is desirable behaviour for most business -oriented classes.
For your second question, the declaration is likey being used to prevent copying the object.
From the C++ Reference Guide by Danny Kalev
Question: How Can I Prevent
Object-Copying?
Answer: Declare the copy constructor
and the assignment operator as private
members, without defining them. Any
statement that involves direct or
indirect copying of that class will
cause a compilation error. This
technique isn’t exactly the picture of
elegance, but in contemporary C++
there’s no other way to block copying
inexpensively.
Regarding your edit:
It simply means that the function has been declared, but not defined. The compiler knows it exists, so it is legal to call it. But it will generate a linker error, unless the compiler is actually able to find the body somewhere.
Typically, you define the function in a header file, and then in the .cpp file, you have something like
// Assuming the class it is a member of is called Foo
Foo& Foo::operator=(const CString& str) {
...
}
The only thing to note here is the Foo:: prefix. Because this definition is outside the class definition itself, we have to use this prefix to specify that the operator= we're defining belongs to the Foo class.
returning ANYTHING but an lval is typically wrong and is only used in very special situations
certainly returning a const reference precludes assignment chaining (a=(b=c)), and part of the point of operators is to make classes behave like built in types
Well, that's an assignment operator. It helps one define how other objects (both of the same and other types) are assigned to an instance of the class it is defined within.
The correct syntax is (assuming your class is called 'Object'):
const Object& operator=(const Object& other)
{
// copy members, one at a time.
this->member1 = other.member1;
return *this;
}
Notice the return type is constant. This is a to avoid semantically incorrect, syntactically correct statements such as:
Object A, B, C;
(A = B) = C;
If you define the return type as constant, the above code will not compile (reasonable enough, since it's really messed up) while leaving out the const will allow such bad code to compile, and of course someone will pull their hair trying to figure out what's wrong.
P.S. You might want to think it through: what would happen if you leave out the const from the return type and execute the (A = B) = C; code?
Regarding the follow-up question, the return type can be anything in this case. However, since most assignment operators return a reference to the class in which they are declared, it would be best to return just that, in order not to confuse the reader.
CString& operator=(const CString& str);
Presumably, this function is declared in the private section of the class. This is the standard idiom to make objects of the class non-assignable.