my code :
Scene::Scene(const std::string &scene_file) : ambient_light(0, 0, 0), background(0, 0, 0){
scene_parser parser(*this);
parser.parse(scene_file);
}
scene_parser is a friend of Scene, and in the parse method it accesses(r/w) the members of Scene. Is this going to cause any problems?
Yes, it's ok to give out a reference to this. However, you usually want to do that when the other object will use the pointer later. Your use case looks like it will use the Scene immediately, before the constructor completes, which is a very slippery slope.
Right now, you're not establishing any invariants after calling parse, so it should be ok, but it's also fragile and easy for future changes to introduce breakage.
In your particular example, no problems should arise.
Generally the problem with giving out this references is that the lifetimes of the two objects don't exactly align and the other object could try to access the referred-to object after it has already been destroyed.
In your example, the scene_parser object is on the stack, so it's lifetime ends at the end of the Scene constructor. There is no possible way it could attempt to access a non-existent object via that this reference you provided, so no problems can arise.
It depends.
Inside the constructor body (i.e. once the initializer list is executed), the object is considered "fully constructed" up to the current type. Therefore, you can reference *this, but any virtual function calls will not use overrided functions in derived classes.
All of your subobjects (members and bases) are constructed by the first statement in the body of the constructor. If your object is in a "valid state" (which is part of the definition of your class, sometimes called the "class invariant") at this point, you can treat it as a fully constructed object and do anything with it. However, virtual lookup does work slightly differently than you may expect or require: if this is a base class (and thus this object is a subobject of something else), the final type hasn't been "assigned" yet. For example, this is one way to call pure-virtual methods and get a runtime error (if those methods don't have definitions, anyway).
A more interesting situation is using this in the constructor initializer; that does have some caveats, but that is also before the constructor body.
Related
My search-fu is good, but this is a difficult one to phrase correctly to find the answer. Basically, after a move ctor/assignment is invoked, is it guaranteed that the only thing that will ever be called on the RHS will be the destructor?
The reason I ask is that I have various things that (for sanity's sake) cannot be in an invalid state. But, far and away the most efficient move scheme would be to swap some stuff into them that the dtor can accept but nothing else could. Else, I have to allocate actual data, no matter how trivial, to keep the RHS in a valid state.
If the dtor is the only thing that will ever get called, then I can get maximum efficiency.
is it guaranteed that the only thing that will ever be called on the RHS will be the destructor?
No. It is well-formed to call member functions of a moved from object. The standard doesn't guarantee that a programmer won't do that.
As the implementor of a class, you can decide that some member functions must not be called on a moved from object, and thus can avoid for example allocating memory. Or, you can decide to not have such requirement. In general, having preconditions can allow more efficient implementation, while not having preconditions makes the class easier to use.
As the user of a class, you are responsible for following the preconditions of the member functions that you call (or member access). If a precondition of a function is that class is not in a moved from state, then don't break that precondition.
As a general rule, it's probably a good design to allow assignment operator to be called on a moved from object. That's what all (assignable) standard library classes do.
In short: There is no such guarantee by the standard, but you can impose such requirement on the user of the class. Just make sure it is well documented.
There’s nothing magic about moving from an object. After a move the object is still valid and if it’s not a temporary your code can call member functions on it and pass it to functions.
Just like any other object, and this is really the point of the question, the compiler won’t do anything to an object other than destroy it at the end of its lifetime. For a temporary object, that’s the end of the full statement that creates the object. For a named object, that’s the end of the scope in which the object is created.
In my quest to learn C++ I stumbled across the article Writing Copy Constructors and Assignment Operators which proposes a mechanism to avoid code duplication across copy constructors and assignment operators.
To summarise/duplicate the content of that link, the proposed mechanism is:
struct UtilityClass
{
...
UtilityClass(UtilityClass const &rhs)
: data_(new int(*rhs_.data_))
{
// nothing left to do here
}
UtilityClass &operator=(UtilityClass const &rhs)
{
//
// Leaves all the work to the copy constructor.
//
if(this != &rhs)
{
// deconstruct myself
this->UtilityClass::~UtilityClass();
// reconstruct myself by copying from the right hand side.
new(this) UtilityClass(rhs);
}
return *this;
}
...
};
This seems like a nice way to avoid code duplication whilst ensuring "programatic integrity" but needs weighed against the risk of wasting effort freeing-then-allocating nested memory that could, instead, be re-used (as its author points out).
But I'm not familiar with the syntax that lies at its core:
this->UtilityClass::~UtilityClass()
I assume that this is a way to call the object's destructor (to destroy the contents of the object structure) whilst keeping the structure itself. To a C++ newbie, the syntax looks like a strange mixture of an object method and a class method.
Could someone please explain this syntax to me, or point me to a resource which explains it?
How does that call differ from the following?
this->~UtilityClass()
Is this a legitimate call? Does this additionally destroy the object structure (free from heap; pop off the stack)?
TL;DR version: DO NOT FOLLOW ANY ADVICE GIVEN BY THE AUTHOR OF THAT LINK
The link suggests that this technique can be used in a base class as long as a virtual destructor call is not used, because doing so would destruct parts of the derived class, which isn't the responsibility of the base class operator=.
This line of reasoning totally fails. The technique can never ever be used in a base class. The reason is that the C++ Standard only allows in-place replacement of an object with another object of the exact same type (see section 3.8 of the Standard):
If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:
the storage for the new object exactly overlays the storage location which the original object occupied, and
the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and
the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is const-qualified or a reference type, and
the original object was a most derived object (1.8) of type T and the new object is a most derived object of type T (that is, they are not base class subobjects).
In the original code, both return *this; and subsequent use of the object are undefined behavior; they access an object which has been destroyed, not the newly created object.
This is a problem in practice as well: the placement-new call will set up a v-table ptr corresponding to the base class, not the correct derived type of the object.
Even for leaf classes (non-base classes) the technique is highly questionable.
TL;DR DO NOT DO THIS.
To answer the specific question:
In this particular example, there's no difference. As explained in the article you link to, there would be a difference if this were a polymorphic base class, with a virtual destructor.
A qualified call:
this->UtilityClass::~UtilityClass()
would specifically call the destructor of this class, not that of the most derived class. So it only destroys the subobject being assigned to, not the entire object.
An unqualified call:
this->~UtilityClass()
would use virtual dispatch to call the most derived destructor, destroying the complete object.
The article writer claims that the first is what you want, so that you only assign to the base sub-object, leaving the derived parts intact. However, what you actually do overwrite part of the object with a new object of the base type; you've changed the dynamic type, and leaked whatever was in the derived parts of the old object. This is a bad thing to do in any circumstances. You've also introduced an exception issue: if the construction of the new object fails, then the old object is left in an invalid state, and can't even be safely destroyed.
UPDATE: you also have undefined behaviour since, as described in another answer, it's forbidden to use placement-new to create an object on top of (part of) a differently-typed object.
For non-polymorphic types, a good way to write a copy-assignment operator is with the copy-and-swap idiom. That both avoids duplication by reusing the copy-constructor, and provides a strong exception guarantee - if the assignment fails, then the original object is unmodified.
For polymorphic types, copying objects is more involved, and can't generally be done with a simple assignment operator. A common approach is a virtual clone function, which each type overrides to dynamically allocate a copy of itself with the correct type.
You can decide to how to call the destructor:
this->MyClass::~MyClass(); // Non-virtual call
this->~MyClass(); // Virtual call
I have looked at the related questions such as here and here about this topic, and they all describe object slicing, but none of them address whether it is safe, reliable and predictable.
Is there a guarantee from either the standard or the compiler, that if I pass a subclass object by value to a method which wants a superclass, the parts that are sliced off are exactly the members of the subclass, and I will be able to use the sliced superclass object without any concerns about undefined behavior?
Yes, it is safe, reliable, and predictable, because it is well defined by the standard (it will just copy construct a base class object from the derived class object).
But no, it is not safe, it should not be relied on, and generally be treated as unpredictable, because your readers won't know what's going on. This will trigger a lot of bugs when others try to modify your code later (including your own future self). It is basically a no-no, much in the same way as the goto statement, which is perfectly well defined, reliable, and predictable as well.
When they say "parts are sliced off" they do not mean that these parts somehow "disappear": all they mean that these parts are not copied into the object presented to your function for the corresponding parameter. In this sense, object slicing is not dangerous or poorly defined.
What happens there is rather straightforward: in order to construct the value of the parameter that you are passing by value, the object of the derived class used for the actual parameter is given to the constructor of the base class to make a copy. Once the copy constructor has completed its work, you have an object of the base class.
At this point you have a fully functioning object of the base class. The compiler guards you against accepting a class with pure virtual members by value, so you wouldn't be able to slice your object into an instance with missing pure virtual functions.
A more important question is whether you want the slicing behavior to happen implicitly: there is nothing the compiler does here that you wouldn't be able to do in your code:
void foo(bar b) {
... // Payload logic
}
gives you the same functionality as
void foo(const bar &r) {
bar b(r);
... // Payload logic
}
With the first snippet, it is very easy to miss the fact that an ampersand is missing after the name of a type, leading the readers to think that the polymorphic behavior is retained, while it is, in fact, lost. The second snippet is easier to understand to people who maintain your code, because it makes a copy explicitly.
Whenever an object is constructed, should the constructor always leave it in an "initialised" state?
For example, if an Image class has two constructors where one takes a file path string, and the other takes no parameters, is it bad practice for the latter to leave the image object in an invalid state?
Assuming the class is written to handle both states.
I ask this because I find it almost necessary to have a default construct in a lot of cases. Especially when an object is a member of a class and you want to initialise it IN the constructor of that class.
EDIT: I am aware of the member initialiser list. I have found a few situations where I would like to construct the object DURING the constructor of the class it is held in, not before. Although, I understand that this could potentially be more dangerous than any other alternative.
It all boils down to the definition of a "valid state": if the methods of your class handle the state when the path is empty, then the state with the empty path is a valid state, and is definitely acceptable.
This may not be optimal from the coding perspective, though, because potentially you might need to add multiple checks for the path to be valid. You can often manage complexity by implementing the State Pattern.
I find it almost necessary to have a default construct in a lot of cases. Especially when an object is a member of a class and you want to initialise it IN the constructor of that class.
You do not need a default constructor in order to initialize an object in the constructor of the class of which it is a member, as long as you construct the dependent in the initialization list.
Your last line:
I ask this because I find it almost necessary to have a default construct in a lot of cases. Especially when an object is a member of a class and you want to initialise it IN the constructor of that class.
Implies that you are not using member initializer lists. You do not need a default constructor in this case. Example:
class Member {
public:
Member(std::string str) { std::cout << str << std::endl; }
};
class Foo {
public:
Foo() : member_("Foo") {}
private:
Member member_;
}
Additionally, your question title and body conflict and the terminology is a bit vague. When constructing, it is usually best to leave the object in a valid and usable state. Sometimes the second aspect (being usable) is less necessary, and many solutions require it. Further, in C++11, moving from an object must leave it in a valid state, but doesn't necessarily (and in many cases shouldn't) leave it in a usable state.
EDIT: To address your concern about doing work in your constructor, consider moving the work to either a static member of the Member class, or a private (static or non-static) function in the owning class:
class Member {
public:
Member(std::string str) { std::cout << str << std::endl; }
};
class Foo {
public:
Foo() : member_(CreateFoo()) {}
private:
Member CreateMember() {
std::string str;
std::cin >> str;
return Member(str);
}
Member member_;
};
One danger of this approach, however, is that the intialization order can be important if you use a non-static member function to do the creation. A static function is much much safer, but you may wish to pass some other pertinent member info. Remember that initialization is done in order of member declaration within the class, NOT initializer list declaration order.
Yes, it should always be valid. However, it is usually not very well defined what makes the object valid. At the very least, the object should be usable in a way without crashing. This, however, does not mean that all operations can be performed on the object, but there should be at least one. In many cases, that's just assignment from another source (e.g. std container iterators) and destruction (this one is mandatory, even after a move). But there more operations the objects supports in any kind of state, the less prone to error it will be.
It is usually a trade-off. If you can get away with objects only having states where all operations are valid, that's certainly great. However, those cases are rare, and if you have to jump through hoops to get there, it's usually easier to just add and document preconditions to some of its functionality. In some cases, you might even split the interface to differentiate between functions that make this trade-off and those that do not. A popular example of this is in std::vector, where you need to have enough elements as a precondition to using operator[]. On the other hand, the at() function will still work, but throw an exception.
First, let us define what exactly a "valid state" is: Its an state where the object could do its work.
For example, if we are writting a class that manages a file and let us to write and read the file, a valid state (following our definition) could be an state where the object is holding a correctly oppened file and its ready to read/write on it.
But consider other situation: Whats the state of a moved rvalue?
File::File( File&& other )
{
_file_handle = other._file_handle;
other._file_handle = nullptr; //Whats this state?
}
Its a state where the file object its not ready to write/read on a file, but is ready to be initialized. That is, is a ready to initialize state.
Now consider an alternative implementation of the above ctor using the copy and swap idiom:
File::File() :
_file_handle{ nullptr }
{}
File::File( File&& other ) : File() //Set the object to a ready to initialice state
{
using std::swap; //Enable ADL
swap( *this , other );
}
Here we use the default ctor to put the object on a ready to initialice state, and just swap the passed rvalue with this object, resulting on exactly the same behaviour as the first implementation.
As we have seen above, one thing is a ready to work state, a state where the object is ready to do whats supposed to do, and other completely different thing is a ready to initialize state: A state where the object is not ready to work, but is ready to be initialized and setted up to work..
My answer to your question is: An object is not alwways in a valid state (Its not allways ready to be used), but if its not ready to be used it should be ready to be initialized and then ready to work.
Normally, yes. I've seen a few good counterexamples but they are so rare.
Herb Sutter mentions in one of his http://www.gotw.ca articles that an object is constructed(has valid existence) only if the constructor executes completes.ie to put it in a crude way control passes beyond its final brace.
Now consider the following code
class A
{
public:
A()
{
f();
}
void f()
{
cout << "hello, world";
}
};
int main()
{
A a;
}
Now from what Herb says, can't we say that since A is not completely constructed inside its constructor Calling f() inside the constructor is invalid as the "this" ptr is not ready yet.
Still there is indeed a valid "this" inside the constructor and f() does get called.
I don't think Herb is saying something incorrect... but guess i am interpreting it incorrectly....can some explain to me what exactly that is?
Here is the link to the article : http://www.gotw.ca/gotw/066.htm
It talks about exceptions from constructors. Specifically here is the extract from it on which my question is based:
-When does an object's lifetime begin?
When its constructor completes successfully and returns normally. That is, control reaches the end of the constructor body or an earlier return statement.
-When does an object's lifetime end?
When its destructor begins. That is, control reaches the beginning of the destructor body.
Important point here is that the state of the object before its lifetime begins is exactly the same as after its lifetime ends -- there is no object, period. This observation brings us to the key question:
We might summarize the C++ constructor model as follows:
Either:
(a) The constructor returns normally by reaching its end or a return statement, and the object exists.
Or:
(b) The constructor exits by emitting an exception, and the object not only does not now exist, but never existed.
Now from what Herb says, can't we say
that since A is not completely
constructed inside its constructor
Calling f() inside the constructor is
invalid as the "this" ptr is not ready
yet.
That is only when f() is a virtual method of class A or its inheritance hierarchy and you expect the runtime resolution for f() according to the right object. In simple words, virtual mechanism doesn't kick in if the method is invoked inside constructor.
If f() is not a virtual function, there is no harm in calling it from constructor(s) provided you know what exactly f() does. Programmers usually call class methods like initialize() from constructor(s).
Can you give me the link to the Herb Sutter's article?
By the time program flow enters your constructor, the object's memory has been allocated and the this pointer is indeed valid.
What Herb means, is that the object's state may not have entirely initialized. In particular, if you are constructing a class derived from A, then that class' constructor will not have been called while you are still inside A's constructor.
This is important if you have virtual member functions, since any virtual function in the derived class will not be run if called from within A's constructor.
Note: it would have been easier with the exact article, so that we could have some context
Lifetime considerations are actually pretty complicated.
Considering the constructor of an object, there are two different point of views:
external: ie the user of an object
internal: ie, you when writing constructors and destructors (notably)
From the external point of view, the lifetime of an object:
begins once the constructor successfully completed
ends when the destructor begins to run
It means that if you attempt to access an object mid-construction or mid-destruction Bad Things Happen (tm). This is mostly relevant to multi-threaded programs, but may happen if you pass pointers to your object to base classes... which leads to...
...the internal point of view. It's more complicated. One thing you are sure of is that the required memory has been allocated, however parts of the objects may not be fully initialized yet (after all, you are constructing it).
in the body of the constructor, you can use the attributes and bases of the class (they are initialized), and call functions normally (virtual calls should be avoided).
if it's a base class, the derived object is not initialized yet (thus the restriction on virtual calls)
The implication from the lifetime not having started yet is mainly that, should the constructor throw an exception, the destructor will not be run.
Beware of member variables that are not yet initialized. Beware of virtual functions: the function that you call might not be the one that you expect if the function is virtual and a derived object is created. Other than that, I do not see any problem calling methods from the constructor. Especially the memory for the object has already been allocated.