S
Syam
Fully answered interview questions in c and c++ from
http://www.faiqs.com
http://www.faiqs.com
The answers (at least for the first few questions) are in correct.Syam said:Fully answered interview questions in c and c++ from
http://www.faiqs.com
Fully answered interview questions in c and c++ from
http://www.faiqs.com
Syam said:Fully answered interview questions in c and c++ from
http://www.faiqs.com
Syam said:Fully answered interview questions in c and c++ from
http://www.faiqs.com
Earl Purple said:9. Rule of 3.
The first answer answers it best, although the term "user-defined" was
never actually used, but was probably implied. Generally though if it
needs any of the 3 it needs the other two as well.
Marcus said:I haven't actually checked out the interview question site, but this
article explains why in modern code, one of the 3 is usually a
non-issue, resulting in a "rule of 2":
http://www.artima.com/cppsource/bigtwo.html
Frankly, I've got a number of problems with the article. The factMarcus said:I haven't actually checked out the interview question site, but this
article explains why in modern code, one of the 3 is usually a
non-issue, resulting in a "rule of 2":
http://www.artima.com/cppsource/bigtwo.html
Kai-Uwe Bux said:Hm, interesting piece, but I fail to see the point. They suggest
class Example {
RAII<SomeResource> p_;
RAII<SomeResource> p2_;
public:
Example() :
p_(new SomeResource()),
p2_(new SomeResource()) {}
Example(const Example& other)
: p_(new SomeResource(*other.p_)),
p2_(new SomeResource(*other.p2_)) {}
Example& operator=(const Example& other) {
// Self assignment?
if (this==&other)
return *this;
*p_=*other.p_;
*p2_=*other.p2_;
return *this;
}
~Example() {
std::cout << "Deleting Example, freeing SomeResource!\n";
}
};
where RAII is a variation of auto_ptr<>:
template <typename T> class RAII {
T* p_;
public:
explicit RAII(T* p) : p_(p) {}
~RAII() {
delete p_;
}
void reset(T* p) {
delete p_;
p_=p;
}
T* get() const {
return p_;
}
T& operator*() const {
return *p_;
}
void swap(RAII& other) {
std::swap(p_,other.p_);
}
private:
RAII(const RAII& other);
RAII& operator=(const RAII& other);
};
So far, I am with them. I can see how their Example class does not need a
destructor since that is taken care of by RAII. What I don't see is how
their Example class differs from:
class Example {
SomeResource p_;
SomeResource p2_;
public:
// compiler provided constructors suffice
~Example() {
std::cout << "Deleting Example, no need to free anything!\n";
}
};
After all, in their assignment operator, they do
*p_=*other.p_;
*p2_=*other.p2_;
which rules out a polymorphic use of the pointers since the assignment would
slice. Thus, the proposed solution can only replace non-polymorphic uses of
pointers and for those offers deep copy semantics. That seems to be
pointless. What is it that I am missing?
Earl said:You are missing the point that when Example has two instances of
SomeResource, then that class must be complete at the point of the
header file, whereas if it is contained in a smart pointer then it can
possibly be incomplete at the class declaration level which can be an
advantage in real life where it is in a separate header file.
There is also no guarantee at the header level that the class
SomeResource is copyable and assignable, but the implementation here
takes advantage of the fact that it is. Otherwise your copy constructor
could be implemented something like other.reset( p->clone() ), which
might allow polymorphic classes too.
For both of those cases, I would just use a run-of-the-shelve smart pointer
like shared_ptr or a copy_ptr. Then again, the compiler generated copy
assignment operator, copy constructor, and destructor would be fine:
class Example {
copy_ptr< SomeResource > p_;
copy_ptr< SomeResource > p2_;
public:
// compiler provided constructors suffice
~Example() {
std::cout << "Deleting Example, no need to free anything!\n";
}
};
I still don't see how the Rule of Three turns into a Rule of Two. To me,
that appears to be an artifact of the wicked design of their RAII class.
Fully answered interview questions in c and c++ from
http://www.faiqs.com
Ron said:Frankly, I've got a number of problems with the article. The fact
that they make an owned pointer class to destruct the thing as
an argument that there is only a RULE of 2 is particularly spurious.
If you are going to make a smart pointer class to handle destruction
why not give it COPY SEMANTICS. Then you can get rid of the
copy constructor and assignment operator as well. With well
designed classes it's usually THREE or NOTHING.
Earl said:Show me how you would implement clone_ptr< T > that will work fully
when T is incomplete?.
Note that although it requires T to be complete
on destruction, you can get around that by declaring the destructor in
your class then giving it an empty implementation. I don't know any way
of doing that with copy-construct and assign.
Kai-Uwe Bux said:I am willing to take the challenge. However, I am not certain I understand
the requirement "works fully when T is incomplete". Could you provide a
test case that you want to compile and produce specified output so that I
can see whether I am meeting your requirements before posting a solution?
Huh? What does "it" refer to: the clone_ptr or T?
Earl said:The clone_ptr will be complete. T will not be.
Earl said:The clone_ptr will be complete. T will not be.
This example should work:
// outer.hpp
class Inner;
#include "clone_ptr.hpp"
class Outer
{
clone_ptr< Inner > inner;
public:
explicit Outer( int init = 0 );
int get_value() const;
void set_value( int x );
~Outer(); // must be implemented empty
};
// main source file:
#include "outer.hpp"
#include <iostream>
int main()
{
Outer o1( 10 );
Outer o2( o1 );
Outer o3;
o3 = o2; // test assignment
Outer o4( o3 );
o3.set_value( 20 ); // to check we are modifying only a clone
std::cout << "o1=" << o1.get_value() << ", o2=" << o2.get_value()
<< ", o3=" << o3.get_value() << ", o4=" << o4.get_value()
<< '\n';
}
- You should implement the Inner class, outer.cpp and clone_ptr.hpp
- It should output o1=10, o2=10, o3=20, o4=10
- You may not add any more members to the class Outer.
You should also be able to get it to work with 3 different examples of
Inner:
- 1. Where it uses regular copy-construction.
- 2. Where it uses a clone method and Inner is the actual class
- 3. Where it uses a clone method and the actual class created derives
from Inner.
(I will allow you to put clone_ptr into a namespace if you want but
that is the only change you may make)
o1=10, o2=10, o3=20, o4=10g++ -g -c -o inner.o inner.cpp
g++ -g -c -o outer.o outer.cpp
g++ -g main.cpp outer.o inner.o
a.out
Kai-Uwe Bux said:template < typename T >
T* default_clone ( T* p ) {
return ( p->clone() );
}
explicit
clone_ptr ( pointer ptr )
: the_cln ( &default_clone<value_type> )
, the_del ( &default_delete<value_type> )
, the_ptr ( ptr )
{}
The above assumes that inner has a method clone(). I think, if clone() is
virtual, the above should also work when you use a class derived from
inner. I have, however, not tested that.
If you want to use the copy constructor from inner, just use:
template < typename T >
T* default_clone ( T* p ) {
return ( new T ( *p ) );
}
If you want to make that work with derived classes, you need a templated
constructor like shared_ptr:
template < typename D >
explicit
clone_ptr ( D* ptr )
: the_cln ( &default_clone<D> )
, the_del ( &default_delete<D> )
, the_ptr ( ptr )
{}
Again, I have not tested that, yet.
Earl said:I would have made the cloner a settable parameter too. I would provide
one by default with the option of having others too.
Sure.
If you're very clever then you work out whether or not the class has a
clone() method. If it does you use that as the default cloner, if not you
use the copy constructor.
Again this would just be the default, so it would be
possible to specify a different cloner, but that would be done by the
constructor.
Your implementation of clone_ptr has not quite passed the test as in
its present state it is intrusive to the way its object clones.
I know we can fix that.
Do you think, by the way, it would be a useful addition to boost?
Kai-Uwe Bux said:I think, that's a tough one: I know template magic to figure out whether a
type has a clone method. However, I doubt that it works on incomplete
types. For those, the copy constructor would be selected even when a clone
method is available for the complete type.
What do you mean by "intrusive"?
Maybe. Here is how I would provide for custom-clone objects and deleters:
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.