Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I've noticed this weird behaviour/bug where a class method is called before the actual object is initialized. I have a wrapper object, which has operator->() method. Now, when I'm passing the object to another object as constructor parameter in a constructor using the operator->() method, the actual wrapper object doesn't get constructed, but rather just runs the operator->() method.
As the actual code sample is pretty complicated and depends on many other things, I'll just show C++ code snippet which may not compile properly:
template<typename T>
class wrapper_object_type
{
public:
wrapper_object_type() {/*does not run*/}
T* operator->() {/*does run*/}
};
class bad_behaviour
{
public:
bad_behaviour() : another_object(wrapper_object->t_object)
{/*crashes(0xccc access violation*/}
};
So is there something defined in the standard that may allow such behaviour? Or more accurately, are there some implicit constructions etc. which could bypass the default construction?
Probably you use wrapper_object before it gets initialized. Member variables are constructed in the same order in which they are declared in the class, so make sure wrapper_object is declared before another_object.
(Assuming wrapper_object and another_object are members variables of bad_behaviour, but without a more reasonable code sample it's hard to say.)
Well I did it the hardway; I switched the objects from stack to heap and initialized them explicitly via new keyword rather than in initializer list. As I thought, that didn't reproduce the weird behaviour, so it worked as intended. What I'm thinking now, is that it may be actually a compiler bug, since the way I did it via initializer list is analog to how I fixed the problem. Only thing that changed was the fact that I didn't allocate them in heap before.
I also tried to provide working code which reproduces the bug, but the bug wasn't shown there. It may be because the actual code where the bug was noticed, relies quite heavily to template types and wrapper objects. As it works now when the objects are allocated in heap, the bug isn't in the code but rather in the compiler.
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 6 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
I have a piece of code like this:
class EducationalCentre
{
string _centreName;
vector<Course> _courses; // courses offered by the Centre
Collection<Course*, Student*, 150> _applicants;
public:
EducationalCentre(string name="<name>")
{
_centreName = name;
}
EducationalCentre(const EducationalCentre& obj)
:_courses(obj._courses), _applicants(obj._applicants)
{
_centreName = obj._centreName;
}
};
Now, in this part _applicants(obj._applicants) copy construction header, there's a squiggly red line around (obj, hovering it the error says something about type incompatibility (const being mentioned).
Since I don't want to change anything at this stage (this is a part of exam test) - I would like to know why is that happening.
I tried removing the const from EducationalCentre(const EducationalCentre& obj) and that indeed solves the problem but.. As I said, I would rather learn about what causes this instead of removing it.
Rule for using const is to use it whenever you can :)
Of course, like with all best practices there are exceptions, but in general you should always strive to make non-static methods const if they don't mutate the state of the object.
The reason for the problem you get is that Collection copy constructor takes a non-const reference to the instance it uses as a source object.
Copy constructor can take const or non-const reference as its argument but, IMO, non-const should only be used when you have no choice, which is rarely. Creating an object based on another object should not change the source object, thus it should be marked as const.
As I noted in the comment, the class being generic has nothing to do with copy ctor taking const reference. Indeed, if you take a look at e.g. std::vector you will see that it has a copy constructor which takes a const reference. Probably some of methods you use in Collection copy constructor on your argument is non-const and that is why you can't make argument const. The solution is to make the offending method const, too.
This brings us to an important point: constness is viral. If you mark a method const, all other method it calls on itself must also be const. Same for calling methods on const objects - you can only call const methods. If you don't do it from the beginning, you may end up in situation where making one method const results in changing a whole chain of other methods, so it is easier to give up.
Why constness is good: most bugs are caused by mutating application state in unexpected ways - just ask functional programming fans who rave about immutability :). A const method can't change the state of the object, so it eliminates the possibility of unexpected changes: e.g. if an exception is thrown in the middle of a const method, you can be sure that the object is not in some half-modified state which invalidates class invariants.
Now, C++ is not only an object oriented language, so you can change the application state in other ways, and also you can misuse mutable and const_cast to trick the compiler, but using const helps a lot in writing correct software and lowering the debugging efforts.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Is the following code safe?
struct Foo {
Foo bar() { return *this; }
} foo;
foo = std::move(foo).bar(); // is this safe?
I'm wondering if calling methods on an rvalue is safe.
In general, calling a function on an rvalue is no more or less safe than calling it on an lvalue.
As for your specific code, no movement actually happens. std::move(foo) converts it into an rvalue, which is irrelevant to the call to Foo::bar since it doesn't care whether this is an lvalue or an rvalue. bar will return a copy of foo, which will then be copied back into foo.
The same thing would have happened if you hadn't used std::move at all. std::move doesn't actually move anything; it simply converts it into an rvalue which can participate in a move operation.
Your real question is this: for any type T which is moveable, is this legal:
T t;
t = T(std::move(t));
The answer is... maybe. The state of a moved-from object is exactly what the writer of T chooses for it to be. For most standard library types, it will be "valid-but-unspecified". This means that you can use functions that don't require preconditions, that will work regardless of the current state.
Move assignment is usually such a function, so that will generally work. Will it work for all types? There is nothing which guarantees that it will. It depends on how move support is implemented for each type. Some user-defined types can't achieve even a "valid-but-unspecified" state, which means the only thing you're allowed to do with a moved-from object is destroy it.
It all depends on how users choose to work. However, I would say that a type for which t = T(std::move(t)) does not work (that is, yields undefined behavior) would be a very ill-behaved type.
Not super safe, it is sometimes hard to break down, if it's just for a simple program/game it should be fine, I would recommend that you use a more secure code for a big program :)
Overall it's not going to be too bad if it breaks.
What I mean by super safe is that it can't handle a break, if you decide to use a function of a standard way of doing it (e.g: using Struct like you have)
Sorry I can't supply as much information as I can, I'm newish to struct
if anyone wants to edit my answer they can.
Thanks,
~Coolq
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
When I was learning C++, I was told that if you want to have multiple classes reference the same object, you should give both a pointer to the object. In Modern C++, I'd probably interpret this as the object being a unique_ptr and the classes holding non-owning-raw-pointers.
Recently, my mentor at work suggested that you should only use pointers when you plan on having the store point to a different object or null at some point. Instead, you should store references in classes.
Reference member variables are a thing I've actually never seen before, so I was looking for advice on what the concerns were... It makes sense... You're saying that this reference is assumed to never be null... I guess the concern would then be that you couldn't /check/ for null. It would have to be an invariant of your class...
How about how this applies to using the references for polymorphism?
Update:
The answer that I selected covers my questions pretty well, but I thought I'd clarify for future readers. What I was really looking for was an idea of the consequences of using a reference rather than a pointer as a class member. I realise that the way the question was phrased made it sound more like I was looking for opinions on the idea.
Should I store references in classes in c++?
yes, why not. This question is IMO 'primarily opinion-based', so my answer is based on my own experience.
I use member references when I dont need what pointers have to offer, this way I limit possiblity that my class will be wrongly used. This means among other possibility to bind new value, assign nullptr, you cant take pointer to reference, you cannot use reference arithmetics - those features are missing in references. You should also remember that reference is not an object type, this means among others that if you put a reference as struct member, then it is no longer POD - i.e. you cannot use memcpy on it.
You should also remember that for classes which have non static reference member, compiler will not generate implicit constuctors.
For me this means references as variable members are mostly usefull when class is some kind of wrapper, or a holder. Below is an example which also shows an alternative implementation using pointer member type. This alternative implementation gives you no additional benefit to the reference one, and only makes it possible to introduce Undefined Behaviour.
struct auto_set_false {
bool& var;
auto_set_false(bool& v) : var(v) {}
~auto_set_false() { var = false; }
};
struct auto_set_false_ptr {
bool* var;
auto_set_false_ptr(bool* v) : var(v) {}
~auto_set_false_ptr() { *var = false; }
};
int main()
{
// Here auto_set_false looks quite safe, asf instance will always be
// able to safely set nval to false. Its harder (but not imposible) to
// produce code that would cause Undefined Bahaviour.
bool nval = false;
auto_set_false asf(nval);
bool* nval2 = new bool(true);
auto_set_false_ptr asf2(nval2);
// lots of code etc. and somewhere in this code a statement like:
delete nval2;
// UB
}
It is generally not a good idea to store references in a class because the class cannot be default constructed, copy assigned, move assigned, and the member cannot be changed (the reference cannot be rebound).
That renders the class uncopieable. It therefore cannot be copied, moved or placed in most containers. The far more flexible and less surprising solution is to store a pointer or a std::refernce_wrapper.
IMO references works like pointers.
The only difference is in dynamic_cast: a failed cast produces a nullpointer with pointers, and results in a throw an exception with references.
References are far better than pointers because of one reason: you don't have to play with nulls.
A reference can't be null and it is a big value to not have to check for nulls.
The small difficulty is that you have to assign reference member in a constructor.
But you can definitely change it later to other non-null value pointing to an object of a class of the member or subclass of this class.
So it supports inheritance like pointers do.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Suppose we declare A to be of type Type:
Type A;
Question: is the Type constructor for A called at this point? Or is it only after we initialize A that a constructor is called?
is the Type constructor for A called at this point? Or is it only after we initialize A that a constructor is called?
You are initializing A here, whether you explicitly provided a value for that process or not.
There is no opportunity to initialise A "later"; you can only assign to it later. (Early C texts talk about "initialising" numeric values long after declaration, but that's a different language, a different century, and a different set of descriptive idioms.)
So, yes, the constructor is called as soon as the object's lifetime begins. That's either right there and then, on that line, or if a class member then of course it's when the encapsulating class is being initialised and it's this member's turn.
Of course you could have proven this with a simple std::cout pair.
Yes, it is called immediately. When you assign it a value, the assignment operator is called instead.
The only exception is this:
Type a = value;
Here some compiler with some settings may relax it and call constructor directly with the value as parameter. But it still needs to be part of declaration.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I've searched but couldn't find any results (my terminology may be off) so forgive me if this has been asked before. I'm probably using the wrong search keywords.
I understand how vtables are used to handle virtual function calls on a pointer, specifically when "use after free" vulnerabilities come into play.
However, suppose you have a pointer to myclass and you call function myfunction on it when myfunction is NOT implemented virtually?
According to a bit of reading, there is one less fetch, IE instead of fetching the address of the function, then fetching the function, then calling, it is fetched directly.
Howver what confuses me is how this would work if the pointer to myclass had been freed before use.
EDIT: previous paragraph unclear, I am trying to figure out what sort of undefined behaviour might be expected.
Can anyone clear this up for me? If my question is unclear I will clarify...
CodeLion
EDIT:
MyClass *myclass;
free(myclass);
myclass->DoSomething();
Declaration of DoSomething()
void DoSomething{...} // NOT virtual void DoSomething
The short answer is undefined behaviour.
The long answer is based off a typical C++ implementation.
For a non-virtual method, the method is basically a function with an extra parameter that is automatically passed called this: often an atypical calling convention is also used, but that does not matter much.
So foo->method() becomes Foo::method(foo) in effect, and passing a bad (freed) foo is just like passing any other bad/freed parameter.
Relying on this is a bad idea, as the compiler is free to mess with you if you use an invalid this to invoke a non-virtual method.
This is because the address of the function is known at compile time because it can't possible be anything else. Whereas with a virtual function it needs to use the vtable to determine what function to call at runtime.
If the memory where your pointer to the object the method is being called on was already freed then it would just be undefined behavior the same as if it was a virtual function call because the pointer doesn't point to an instance of My class.
Let me make a different interpretation of the OP's question.
If DoSomething is a virtual function, then
myclass->DoSomething () ; // Should be my object
requires the compiler to generate code that examines the object reference by my class and determine what DoSomething to call at run time. If myclass has been deleted
delete myclass ;
then the behavior during this lookup is undefined and the translation process itself provides a point of failure.
If DoSomething is a non virtual function then, this does not require the compiler to implement a procedure to determine which DoSomething to call at run time. The compile might use the exact same process is uses with a virtual function but this would not strictly be necessary. Assuming that the compiler does not generate code for a run time lookup, doing something like
CALL MyClass_DoSomething
then this would not provide a point of failure for an undefined object referenced by myclass. However, the method needs to know which object called it. The compiler is likely to do this as an argument, doing something like for your code:
MOV EAX, myclass
CALL MyClass_DoSomething
or
PUSH myclass
CALL MyClass_DoSomething
This reference to the object has undefined, indeterminate behavior.