473,414 Members | 1,677 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,414 software developers and data experts.

Object that transfers ownership on assignment/copy

As a possible solution to a problem I'm trying to solve with an
iterator (see an earlier post by me with subject "Iterator
implementation questions: copy constructor and postfix increment"),
I'm trying to implement an object that transfers ownership on
assignment or copy, just like auto_ptr does.

With an auto_ptr, I can do this:

#include <string>
#include <memory>
#include <iostream>

using namespace std;

auto_ptr<stringap_factory() {
return auto_ptr<string>(new string("foo"));
}

int main() {
auto_ptr<strings = ap_factory();
auto_ptr<strings2 = s;
cout << "s1=" << s.get() << ", s2=" << *s2 << endl;
}

and when "s2 = s" executes, the pointer that was held by "s" is
trasferred to "s2", and then the pointer in "s" is set to NULL. So, I
see this output:

s1=0, s2=foo

When I try to implement the same behavior in my own class, I have
compilation problems. Here's my small test case:

#include <string>
#include <iostream>
using namespace std;

class C {
public:

C(string *_s) : s(_s) { }

C(C &that) : s(that.s) { }

C& operator=(C &that) {
if (&that != this) {
s = that.s;
}
return *this;
}

const string *get() {
return s.get();
}

private:
auto_ptr<strings;
};

C c_factory() {
return C(new string("foo"));
}

int main() {
C myC = c_factory();
C myC2 = myC;
cout << "myC=" << myC.get() << ", myC2 = " << *(myC2.get()) << endl;

return 0;
}

When I try to compile this, I get:

test8.C: In function C c_factory():
test8.C:28: error: no matching function for call to C::C(C)
test8.C:10: note: candidates are: C::C(C&)
test8.C:8: note: C::C(std::string*)
test8.C: In function int main():
test8.C:32: error: no matching function for call to C::C(C)
test8.C:10: note: candidates are: C::C(C&)
test8.C:8: note: C::C(std::string*)

The problem seems to be that class C doesn't have a copy constructor
for "const C&" but only "C&", which is appropriate since the copied
object will be destroyed. I can verify this is the problem by
creating a constructor for "const C&", and making s mutable so I can
change it without the compiler complaining:

#include <string>
#include <iostream>
using namespace std;

class C {
public:

C(string *_s) : s(_s) { }

C(C const &that) : s(that.s) { }

C& operator=(C &that) {
if (&that != this) {
s = that.s;
}
return *this;
}

const string *get() {
return s.get();
}

private:
mutable auto_ptr<strings;
};

C c_factory() {
return C(new string("foo"));
}

int main() {
C myC = c_factory();
C myC2 = myC;
cout << "myC=" << myC.get() << ", myC2 = " << *(myC2.get()) << endl;

return 0;
}

compiles and gives the expected output:

myC=0, myC2 = foo

Clearly, though, using "mutable" in this way is a hack.

Is there a better solution to this problem? auto_ptr seems not to have
a copy constructor that requires a const object, so there must be a
way, but I've looked at the source code for g++'s auto_ptr and can't
figure out what magic is making this work.

Thanks for any advice,

----ScottG.
Sep 5 '07 #1
7 1794
Scott Gifford wrote:
As a possible solution to a problem I'm trying to solve with an
iterator (see an earlier post by me with subject "Iterator
implementation questions: copy constructor and postfix increment"),
I'm trying to implement an object that transfers ownership on
assignment or copy, just like auto_ptr does.

With an auto_ptr, I can do this:

#include <string>
#include <memory>
#include <iostream>

using namespace std;

auto_ptr<stringap_factory() {
return auto_ptr<string>(new string("foo"));
}

int main() {
auto_ptr<strings = ap_factory();
auto_ptr<strings2 = s;
cout << "s1=" << s.get() << ", s2=" << *s2 << endl;
}

and when "s2 = s" executes, the pointer that was held by "s" is
trasferred to "s2", and then the pointer in "s" is set to NULL. So, I
see this output:

s1=0, s2=foo

When I try to implement the same behavior in my own class, I have
compilation problems. Here's my small test case:

#include <string>
#include <iostream>
using namespace std;

class C {
public:

C(string *_s) : s(_s) { }

C(C &that) : s(that.s) { }

C& operator=(C &that) {
if (&that != this) {
s = that.s;
}
return *this;
}

const string *get() {
return s.get();
}

private:
auto_ptr<strings;
};

C c_factory() {
return C(new string("foo"));
}

int main() {
C myC = c_factory();
Here you have a temporary from which you're trying to construct
an object. That operation requires binding a non-const reference
to the temporary, which is prohibited.

Take a look at how 'auto_ptr' is implemented and follow that instead
of trying to wrap it up.
C myC2 = myC;
cout << "myC=" << myC.get() << ", myC2 = " << *(myC2.get()) <<
endl;

return 0;
}

[..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 5 '07 #2
"Victor Bazarov" <v.********@comAcast.netwrites:
Scott Gifford wrote:
[...]
> C c_factory() {
return C(new string("foo"));
}
[...]
Here you have a temporary from which you're trying to construct
an object. That operation requires binding a non-const reference
to the temporary, which is prohibited.
I assume you mean the above snippet? I can fix this particular error
by replacing using a temporary:

C c_factory() {
C tmp(new string("foo"));
return tmp;
}

but one error still remains:

test8.C: In function int main():
test8.C:33: error: no matching function for call to C::C(C)
test8.C:10: note: candidates are: C::C(C&)
test8.C:8: note: C::C(std::string*)

Take a look at how 'auto_ptr' is implemented and follow that instead
of trying to wrap it up.
The actual code contains more member variables and methods, so it's
not quite as simple as what I posted. Since the auto_ptr code is
nontrivial and I don't understand all of it, I suspect it would be too
error-prone to try and copy its implementation into my class. I will
probably contine using the "mutable" hack if there's not a
straightforward way to make this work.

Thanks again, Victor!

----Scott.
Sep 5 '07 #3
Scott Gifford wrote:
"Victor Bazarov" <v.********@comAcast.netwrites:
>Scott Gifford wrote:

[...]
>> C c_factory() {
return C(new string("foo"));
}

[...]
>Here you have a temporary from which you're trying to construct
an object. That operation requires binding a non-const reference
to the temporary, which is prohibited.

I assume you mean the above snippet? I can fix this particular error
by replacing using a temporary:

C c_factory() {
C tmp(new string("foo"));
return tmp;
}
The variable you call 'tmp' has nothing to do with the "temporary" that
I refered to. A temporary object and an object with automatic storage
duration are not the same. Your 'tmp' here is the latter. The former
is created as the function returns a value.
>
but one error still remains:

test8.C: In function int main():
test8.C:33: error: no matching function for call to C::C(C)
test8.C:10: note: candidates are: C::C(C&)
test8.C:8: note: C::C(std::string*)

>Take a look at how 'auto_ptr' is implemented and follow that instead
of trying to wrap it up.

The actual code contains more member variables and methods, so it's
not quite as simple as what I posted. Since the auto_ptr code is
nontrivial and I don't understand all of it, I suspect it would be too
error-prone to try and copy its implementation into my class. I will
probably contine using the "mutable" hack if there's not a
straightforward way to make this work.
In case you don't read my other reply, think reference counting instead
of transfer of ownership.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Sep 5 '07 #4
Victor Bazarov wrote:
Scott Gifford wrote:
>"Victor Bazarov" <v.********@comAcast.netwrites:
>>Scott Gifford wrote:
[...]
>>> C c_factory() {
return C(new string("foo"));
}
[...]
>>Here you have a temporary from which you're trying to construct
an object. That operation requires binding a non-const reference
to the temporary, which is prohibited.
I assume you mean the above snippet? I can fix this particular error
by replacing using a temporary:

C c_factory() {
C tmp(new string("foo"));
return tmp;
}

The variable you call 'tmp' has nothing to do with the "temporary" that
I refered to. A temporary object and an object with automatic storage
duration are not the same. Your 'tmp' here is the latter. The former
is created as the function returns a value.
Victor,
adding this information may help understanding the problem.

initial value of reference to non-const must be an lvalue
(the compiler assume that you will somewhere modify the original data)

the temporary returned by the function is an rvalue.


--
Thanks
Barry
Sep 6 '07 #5
The original code posted at the top of the thread, compiles on the
MSVC 8 compiler!!
without errors

Does that compiler then allow binding of temporary to non const??

Sep 6 '07 #6
dev_15 wrote:
The original code posted at the top of the thread, compiles on the
MSVC 8 compiler!!
without errors

Does that compiler then allow binding of temporary to non const??
The MSVC has a compile option /Za, which disables the extension. Maybe
that's for some backward compatibility, I guess.
Try it out.

--
Thanks
Barry
Sep 6 '07 #7
On Sep 7, 3:37 am, James Kanze <james.ka...@gmail.comwrote:
>
The need for "move" semantics (a copy where the source will
never be used again) are more general, and the language is being
modified to support them.
In c++0x, there will be a smart pointer called std::unique_ptr. It is
not Assignable or Copyable but is Moveable.

i.e.

std::unique_ptr<intp1(new int);
std::unique_ptr<intp2;

std::unique_ptr<intp3(p1); //illegal
p2 = p1; //illegal

p2 = std::move(p1); // legal, p1 transfers ownership to p2
std::unique_ptr<intp4(std::move(p2)); // legal, p2 transfers
ownership to p4

Chris

P.S. it will also support custom deleters objects. a "deleter" is a
functor with operator()(T* t). std::default_delete basically does
operator(T* t){delete t;} (or delete [] t if T is of type T[] or T[N]
for some int N).

Sep 8 '07 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

106
by: A | last post by:
Hi, I have always been taught to use an inialization list for initialising data members of a class. I realize that initialsizing primitives and pointers use an inialization list is exactly the...
15
by: Tony Johansson | last post by:
Hello! Assume I have a class named Student and I instansiate an object called kasia in this way. Student kasia(100); What the difference if I instead instansiate this kasia in this way....
3
by: jakub.pieczonka | last post by:
I have three classes in my example. Foo, FooRepository and FooImpl. Foo is a lightweight wrapper around FooImpl. The idea is that Foo can be used to pass elements by value from FooRepository to...
30
by: jimjim | last post by:
Hello, This is a simple question for you all, I guess . int main(){ double *g= new double; *g = 9; delete g; cout<< sizeof(g)<<" "<<sizeof(double)<<" "<<sizeof(*g)<<" "<<*g<<" "<<endl; *g =...
6
by: Bart Simpson | last post by:
I have the ff class decl: class ArrayData : public myArray { public: inline ArrayData(){ InitArray(&m_arr);} inline explicit ArrayData(const std::string& name):m_name(name){...
10
by: Jess | last post by:
Hello, If I create a temporary object using a dynamically created object's pointer, then when the temporary object is destroyed, will the dynamically created object be destroyed too? My guess...
14
by: Summercool | last post by:
The meaning of a = b in object oriented languages. ==================================================== I just want to confirm that in OOP, if a is an object, then b = a is only copying the...
0
by: Stodge | last post by:
Hi folks, new to Boost Python and struggling to build a prototype at work. I thought I'd start with a conceptual question to help clarify my understanding. I already have a basic prototype working...
275
by: Astley Le Jasper | last post by:
Sorry for the numpty question ... How do you find the reference name of an object? So if i have this bob = modulename.objectname() how do i find that the name is 'bob'
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.