Re: try to stump me on C++
Quote:
Originally Posted by Zaccheus
The important thing to remember is that even a pure virtual destructor will always need to be defined, even though it is pure virtual, because the derived class will call it. And if it is trivial (or even empty) then it might as well be inlined.
Depends on the definition of "call". :D
Yes the derived class will "invoke" it, but when declared as inline (and the compiler infact in-lines ir) there will no "call" (transfer of control to antherseries of instructions and back, invalidating the processor pipeline). The invocation will simply be optimized out out existance.
Mr Schroedinger is still looking for his cat... ;) ;)
Re: try to stump me on C++
Yeah that was the whole point, getting rid of the invocation by making it inline. :wave:
Quote:
Originally Posted by andersod2
My comments were based on the assumption that the operation was possible
as were mine :)
Quote:
Originally Posted by andersod2
, or that you didn't dereference the "this" pointer
but the code does do that.
Quote:
Originally Posted by andersod2
and were just casting away the uniqueness of everything to make it a legal operation.
Hmm, I don't see how casting comes into it.
Quote:
Originally Posted by andersod2
Otherwise, like you say, I think this operation would probably not even be possible to compile/link at best
why not?
Quote:
Originally Posted by andersod2
, and catastrophic failure at worst.
Which takes us back to my question: "What exactly do you think might happen if the only data member were an std::string or a boost smart pointer?"
Code:
class foo
{
std::string data;
public:
foo( const std::string& str )
: data(str)
{
}
foo( const foo& x )
{
operator=(x); // same as: *this = x;
}
foo& operator=(const foo& other)
{
if(&other != this)
{
data = other.data;
}
return *this;
}
};
Ignoring the fact that the copy constructor & assignment operator are unnecessary in this simple example.
Re: try to stump me on C++
Quote:
Originally Posted by Zaccheus
as were mine :)
but the code does do that.
Hmm, I don't see how casting comes into it.
The original question was, as you say, ambiguous, so it was difficult to determine directly from the code what was intended. So I did not so much look exactly at the code as I did what the poster's point was. I believe the question was intended to reveal a memory leak, though the code does not *exactly* prove this...it's just implied due to lack of other info. The more exact answer would have been your comments, but I didn't get into that.
Quote:
Originally Posted by Zaccheus
why not?
Well, if the operator equals also had a copy construction in it, as we fear, then the best case scenario is that the compiler says "you did some circular stuff" or whatever and fails.
Quote:
Originally Posted by Zaccheus
Which takes us back to my question: "What exactly do you think might happen if the only data member were an std::string or a boost smart pointer?"
Hmm...at first glance I'm not seeing it, other than the same problem as before. I would need to double check the copy constructors and assignment operators of std::string, but I'm guessing that isn't the problem.
Re: try to stump me on C++
Quote:
Originally Posted by andersod2
Hmm...at first glance I'm not seeing it, other than the same problem as before. I would need to double check the copy constructors and assignment operators of std::string, but I'm guessing that isn't the problem.
If you need a hint, the example Zaccheus gave will compile and run fine. The answer you're looking for is more of a stylistic guideline (or "moral") than a specific compile- or run-time problem. Mostly it involves the difference between initialization and assignment, as well as what it means for an object to be "fully constructed".
Can you at least explain the difference between these two pieces of code, and the importance of that distinction?
Code:
// A
int a = 0;
// B
int b;
b = 0;
Re: try to stump me on C++
Another hint is "Exception Safety".
Try to write a (significant) assignment operator that is guarenteed to not have any memory leaks or any partially initialized objects if an exception is thrown at any sequence point.
Re: try to stump me on C++
Quote:
Originally Posted by Hermit
The answer you're looking for is more of a stylistic guideline (or "moral")
Yes, I'm getting the moral part of it, which I think was kind of implied in what Zaccheus was saying before about the problem with the original code. You just don't want your copy constructor and your operator= being dependant on one another. Otherwise the code you posted could produce drastically different results since the first one was copy constructed and the second one was just constructed then assigned with operator=....so but my confusion is perhaps semantic whereas Zacc is saying "what if there was a single member of std::string or a boost smart pointer" which makes it sound as though the problem comes down to having a single member or a specific kind of member. If that's not it, and it's just what you were saying, then, I guess "oh, I see" :P C++ makes it easy to invent new problems that don't exist :)
Re: try to stump me on C++
OK, one more hint...
IF you have a class whos members are either POD, or classes which properly implement their respective copy constructors....
How much code do you have to write ti implement a copy constructor?
Between the last two hints, that should be sufficient...
IF not, please provide your physical location, and I will send someone to do a "Mark Harmon" (reference to TV show NCIS) on you. :D :wave: ;)
Re: try to stump me on C++
Quote:
Originally Posted by TheCPUWizard
IF not, please provide your physical location, and I will send someone to do a "Mark Harmon" (reference to TV show NCIS) on you. :D :wave: ;)
Better a 'Mark Harmon' than a 'Tanya Harding' any day of the week.
Re: try to stump me on C++
Quote:
Originally Posted by TheCPUWizard
Another hint is "Exception Safety".
That's a good point, and a subtle one at that. It is possible to write an exception safe assignment operator without invoking the copy constructor (which would invoke the assignment operator, and so on ad infinitum), even using the no-throw swap method... but it wouldn't be pretty. Basically you'd need a way of effectively creating a copy without using the copy constructor.
Re: try to stump me on C++
Quote:
Originally Posted by Hermit
That's a good point, and a subtle one at that. It is possible to write an exception safe assignment operator without invoking the copy constructor (which would invoke the assignment operator, and so on ad infinitum), even using the no-throw swap method... but it wouldn't be pretty. Basically you'd need a way of effectively creating a copy without using the copy constructor.
1) Unfortunately many people do not consider excptions as they are writing each line of code.. :mad: :sick:
2) There is a big difference between "possible" and "practical", which i think we agree on... :wave:
Re: try to stump me on C++
> Another hint is "Exception Safety".
True. You would need a well-defined constructor to begin with and a routine that equates to a destructor called from your catch block.
> IF you have a class whos members are either POD, or classes which
> properly implement their respective copy constructors....
> How much code do you have to write ti implement a copy constructor?
I think there is some confusion here as to whether you and Zacc are referring to the same thing. I alluded to the answer to this question earlier when saying that the copy constructor will be implemented automatically. What I didn't say was that the implementation will include a member-wise copy (with operator=), which, under the conditions you gave, should work out well, requiring no real code to be written. Like I say I don't recall the specifics of the operator= for strings and what not. At this point I don't even know what the question is anymore, so go ahead and send Clay Aiken over to sing me a song. I'm certain I'll end up saying "that's what I said, right?"
Re: try to stump me on C++
Quote:
Originally Posted by andersod2
Yes, I'm getting the moral part of it, which I think was kind of implied in what Zaccheus was saying before about the problem with the original code. You just don't want your copy constructor and your operator= being dependant on one another.
Just to be clear, I was saying that the operator= SHOULD be dependent on the copy constructor, but for very practical reasons - the "Exception Safety" which TheCPUWizard mentioned.
Quote:
Originally Posted by andersod2
....so but my confusion is perhaps semantic whereas Zacc is saying "what if there was a single member of std::string or a boost smart pointer" which makes it sound as though the problem comes down to having a single member or a specific kind of member. If that's not it, and it's just what you were saying, then, I guess "oh, I see" :P C++ makes it easy to invent new problems that don't exist :)
I wasn't saying there would be a problem, I was asking what you thought would actually happen. Basically I'm trying to understand what you mean by your answer:
Quote:
Originally Posted by andersod2
basically you never want to modify the "this" pointer, expecially this way. In fact, this could be an example of the worst case scenario use of *this. It is usurping the allocation of the class (major memory leak). It's also potentially wreaking havoc with the "new"-ing of this class, potentially forcing some kind of access violation. Lot's of negative implications with modifying *this, and should almost never be done"
Now my comment on the full class I posted would be this: It will compile, link and run just fine, because std::string default constructs itself to a valid object. However it is not-optimal for the data members to first construct themselves and then be overwritten immediately afterwards. On the other hand, if one of the data members is not of a type which default constructs to a valid object (like a raw pointer which will by default contain garbage) then the program will very likely crash.
Re: try to stump me on C++
Quote:
Originally Posted by Zaccheus
Just to be clear, I was saying that the operator= SHOULD be dependent on the copy constructor, but for very practical reasons - the "Exception Safety" which TheCPUWizard mentioned.
i disagree, first of all it breaks reservation of memory in allocators, second of all this is redundent code. also where is the logic? the same that it would not be logic to call operator= in the copy constructor for many reasons. This all for a "state" of an object, does it really "beak" the instance? as far as i know exceptions have nothing todo with objects, and as far as i know there isnt really a object or instance.
same goes for protecting the copy assignment for assigning to itself, cus first of all there should not be a problem with assigning to itself, i agree there might be a rare case that a class manages it so it cannot assign to itself. second of all its the programmers fault for assigning to itself. third of all the chance that a instance actually assigns to itself its very rare. It only wastes cpu cycles. And trust me when your doing lots of copying these cpu cycles become precious. and dont tell me to goto C then or ASM cause that is bull ****.
also dont tell me these cpu cycles are nothing in modern computers cus if your programming for a 1 watt processor for a laptop this is a diffrenrt story
Re: try to stump me on C++
Mitsukai, I was talking about the following technique:
Code:
MyClass& MyClass::operator=(const MyClass& other)
{
// use copy constructor to create a copy.
// If an exception happens, then 'this will remain unchanged.
MyClass temp(other);
// Use a member function called swap to exchange the internal representations of 'this' and temp, just like std::vector<T>::swap does.
swap(temp); // Cannot throw exceptions!
return *this;
}
Re: try to stump me on C++
so was i
Code:
MyClass& MyClass::operator=(MyClass temp)
{
Swap(temp);
return *this;
}