I'm a java programmer switching over to C++. I have a list of data in a class. I want to return the contents of a list stored in a class variable and then generate a new list and store it in the class variable so I can start adding new data to the empty list. I think I know how to do it, but I want to double check since I'm new to references and c++ memory management and don't want a stupid memory leak later. (note, I can't copy my actual code easily so I'm just rewriting it, forgive me if I mistype anything).
I believe the correct syntax would be something like this:
//mylist is typedef of a list type
mylist& temporaryList=classList;
classList=myList();
return classList;
Is this syntax correct? Also, will I have to worry about freeing either the returned variable or the classList variable at any time or will RIAA take care of it all for me?
Sorry for asking such an easy question, but thank you for confirming my assumptions.
mylist& temporaryList=classList;
tempraryList is a reference. When you change classList, it will change too. Try this:
mylist tempraryList = classList;
This will copy mylist's copy constructor, creating a new one instead of just aliasing the other one.
return classList;
This is returning the one you just decided should be a new list. You want to return temporaryList. Make sure it isn't being returned by reference, though, because temporaryList will go out of scope (cleaning itself up, since it was allocated on the stack) and you'll end up with a dangling reference.
As well, usually, rather than assigning the result of a default constructor, classes might provide a sort of reset function to do that without the overhead of another object.
As #chris points out you have a problem in that you are using a reference, references have the nice feature that they alias the actual object at little to no cost, but in your case it means that when you reset the member list you are resetting the only list in your program.
The trivial naïve fix to your code is, as #chris also points out, to copy the list and then reset the original:
mylist getAndClear() {
mylist temporaryList=classList; // make a copy
classList=myList(); // reset the internal
return temporaryList; // return the **copy**
}
Now, the problem with this approach is that you are incurring the cost of copying when you know that the original list is going to be destroyed immediately. You can avoid that cost by using the copy-and-swap idiom(*):
mylist getAndClear() {
mylist tmp; // empty
swap( tmp, classList ); // swap contents, now classList is empty
// tmp holds the data
return tmp;
}
This is assuming that mylist is a std::list. If it is not, make sure that you implement swap (or in C++11 move constructors, that will enable an efficient std::swap).
(*) While this may not seem a direct application of the copy-and-swap idiom, it actually is, where the modification to be applied is clearing the list. Perform a copy and apply the change over the copy (in this case the copy is avoided, as the change is emptying it), then swap the contents once the operation has completed successfully.
chris mentions using a member function to reset or clear the object like this:
mylist tmp = classList;
classList.clear();
return tmp;
But you can usually do even better by avoiding the copy in the first place.
mylist tmp;
std::swap(tmp,classList);
return tmp;
Also, will I have to worry about freeing either the returned variable or the classList variable at any time or will RIAA take care of it all for me?
You don't need to delete resources unless you new them somewhere. And if you do use new then you should also use smart pointers so you still won't have to delete anything.
One of the most important things to understand about C++ coming from Java is that C++ objects are value-like objects by default. That is:
class A {
bool bar_called;
public:
A() : bar_called(false) {}
void bar() { bar_called = true; }
bool has_bar_been_called_on_this_object() { return bar_called; }
};
void foo(A a) {
a.bar();
}
int main() {
A a;
foo(a);
std::cout << a.has_bar_been_called_on_this_object() << '\n';
}
The output will indicate that bar has not been called on a. Java uses, but tries to hide, pointers. So once you figure out pointers in C++ things should make more sense to you, and then you will be able figure out how to not use pointers.
Object o = new Object(); // Java hides the fact that o is a pointer to an Object, but fails to hide the consequences
Object b = o; // b is a pointer to an object, the same Object o points to.
// Equivalent C++
Object *o = new Object();
Object *b = o;
Judging from the C++ code you presented, in Java you'd do what your asking about something like this:
mylist tmp = classList;
classList = new mylist();
return tmp;
The equivalent in C++ would be:
mylist *tmp = classList; // classList is a pointer to a new'd up list.
classList = new mylist();
return tmp;
However that's not idomatic C++. In C++ you generally don't want to use pointers, and if you do you want to use smart pointers
std::shared_ptr<mylist> tmp = classList; // classList is a std::shared_ptr<mylist>
classList = std::make_shared<mylist>();
return tmp;
or
std::unique_ptr<mylist> tmp = std::move(classList); // classList is a unique_ptr
classList = std::unique_ptr<mylist>(new mylist()); // careful here, don't go calling a bunch of functions inside the mylist initializer, it's dangerous for reason beyond the scope of this post
return tmp;
But the C++ way is really to avoid pointers altogether.
mylist tmp; // classList is not a pointer at all
std::swap(tmp,classList); // the values of classList and tmp are swapped
return tmp; // tmp is returned by value, tmp has the same value as classList, but is not the same object, tmp and classList are objects, not pointers to objects as they are in Java or in the above C++ examples.
Related
Consider a simple class:
class MyInt {
public:
MyInt();
MyInt(const char *num);
};
I want to intergrate reference counting design pattern in to the class, which means i need to keep track of how much pointers point to an instance of this class. I need to implement it in this class only or create a different class and inherit it.
Given this example code i want to clear any allocated memory of the program:
int main() {
MyInt*a = new MyInt("10");
a = new MyInt("20");
delete a;
return 0;
}
My Tries
I tried operator oveloading of '=' and adding referenceCount member:
MyInt &MyInt::operator=(const MyInt* right) {
MyInt*left = this;
*this = right;
left->referenceCount -= 1;
if (left->referenceCount == 0) {
delete (left);
}
return *this;
}
But this does not work because we assign pointer of the class to another pointer.
Also tried to override the new and delete operators but can't seem to make it work and keep track of the number of pointer to an instance.
As it seems i need to implement four things: copy constructor, operator new, operator delete and operator =.
How can i effectivly keep track of the pointers and clear unpointed memory automaticly?
std::shared_ptr does exactly this. From the ref:
Manages the storage of a pointer, providing a limited
garbage-collection facility, possibly sharing that management with
other objects. [...] Once all shared_ptr objects that share ownership
over a pointer have released this ownership, the managed object is
deleted.
so I suggest you use this instead.
a is a pointer, so assigning to a will not involve MyInt::opterator= in any way. There is no way to detect when a pointer to T is assigned to by overloading T's operators. To do this, you would need to design a class type that behaves like a pointer. Then you could properly track when the pointer might leak an object and properly delete it. Fortunately for you, the standard library already provides this class. It's std::shared_ptr. Here is your example modified to use std::shared_ptr :
#include <memory>
struct InfInt {
InfInt(const char *) {}
};
int main()
{
auto a = std::make_shared<InfInt>("10");
a = std::make_shared<InfInt>("20"); // the previous `a` is deleted
// The object pointed to by `a` is automatically deleted when
// the last reference to it goes out of scope
return 0;
}
does the function set::insert saves a pointer to the element or a copy of it. meaning, can I do the following code, or I have to make sure that the pointers are not deleted?
int *a;
*a=new int(1);
set<int> _set;
_set.insert (*a);
delete a;
*a=new int(2);
_set.insert (*a);
delete a;
I gave the example with int, but my real program uses classes that I created.
All STL containers store a copy of the inserted data. Look here in section "Description" in the third paragraph: A Container (and std::set models a Container) owns its elements. And for more details look at the following footnote [1]. In particular for the std::set look here under the section "Type requirements". The Key must be Assignable.
Apart from that you can test this easily:
struct tester {
tester(int value) : value(value) { }
tester(const tester& t) : value(t.value) {
std::cout << "Copy construction!" << std::endl;
}
int value;
};
// In order to use tester with a set:
bool operator < (const tester& t, const tester& t2) {
return t.value < t2.value;
}
int main() {
tester t(2);
std::vector<tester> v;
v.push_back(t);
std::set<tester> s;
s.insert(t);
}
You'll always see Copy construction!.
If you really want to store something like a reference to an object you either can store pointers to these objects:
tester* t = new tester(10);
{
std::set<tester*> s;
s.insert(t);
// do something awesome with s
} // here s goes out of scope just as well the contained objects
// i.e. the *pointers* to tester objects. The referenced objects
// still exist and thus we must delete them at the end of the day:
delete t;
But in this case you have to take care of deleting the objects correctly and this is sometimes very difficult. For example exceptions can change the path of execution dramatically and you never reach the right delete.
Or you can use smart pointers like boost::shared_ptr:
{
std::set< boost::shared_ptr<tester> > s;
s.insert(boost::shared_ptr<tester>(new tester(20)));
// do something awesome with your set
} // here s goes out of scope and destructs all its contents,
// i.e. the smart_ptr<tester> objects. But this doesn't mean
// the referenced objects will be deleted.
Now the smart pointers takes care for you and delete their referenced objects at the right time. If you copied one of the inserted smart pointers and transfered it somewhere else the commonly referenced object won't be delete until the last smart pointer referencing this object goes out of scope.
Oh and by the way: Never use std::auto_ptrs as elements in the standard containers. Their strange copy semantics aren't compatible with the way the containers are storing and managing their data and how the standard algorithms are manipulating them. I'm sure there are many questions here on StackOverflow concerning this precarious issue.
std::set will copy the element you insert.
You are saving pointers into the set.
The object pointed at by the pointer is not copied.
Thus after calling delete the pointer in the set is invalid.
Note: You probably want to just save integers.
int a(1);
set<int> s;
s.insert(a); // pushes 1 into the set
s.insert(2); // pushes 2 into the set.
Couple of other notes:
Be careful with underscores at the beginning of identifier names.
Use smart pointers to hold pointers.
Ptr:
std::auto_ptr<int> a(new int(1));
set<int*> s;
s.insert(a.release());
// Note. Set now holds a RAW pointer that you should delete before the set goes away.
// Or convert into a boost::ptr_set<int> so it takes ownership of the pointer.
int *a;
*a=new int(1);
This code is wrong because you try to use the value stored at address a which is a garbage.
And, every stl containers copy elements unless you use move semantics with insert() and push_back() taking rvalue references in C++0x.
If I create an object on the stack and push it into a list, then the object loses scope (outside of the for loop in the example below) will the object still exist in the list? If the list still holds the object, is that data now invalid/possibly corrupt?
Please let me know, and please explain the reasoning..
Thanks,
jbu
class SomeObject{
public:
AnotherObject x;
}
//And then...
void someMethod()
{
std::list<SomeObject> my_list;
for(int i = 0; i < SOME_NUMBER; i++)
{
SomeObject tmp;
my_list.push_back(tmp);
//after the for loop iteration, tmp loses scope
}
my_list.front(); //at this point will my_list be full of valid SomeObjects or will the SomeObjects no longer be valid, even if they still point to dirty data
}
EDIT: so what if it were a std::list<SomeObject*> my_list; instead of list...in that case would it be invalid?
The standard containers make a copy of the object so the list is still ok in your example.
All containers make a copy of what they store. It's a requirement that an object be copy-constructible and assignable, if it is to be used in a container.
So yes, vector, list, etc. all make a copy of your object.
An even shorter example:
struct foo {};
std::vector<foo> v;
v.push_back(foo());
// makes a copy of the temporary, which dies at the semicolon.
If it didn't make a copy, the above code would be bad.
The following code is not ok:
struct foo {};
std::vector<foo*> v;
{
foo f;
v.push_back(&f); // fine, but...
} // ...now f stops existing and...
v.front(); // ...points to a non-existent object.
Yes, it's valid. push_back makes a copy.
With all STL containers (lists, vectors, maps, everything), the containers make a copy of what you add to the containers so, so long as what you add isn't a pointer or reference, you're safe.
If you write your own containers though, you have to be careful how you do things, since there's nothing stopping you from writing a type of container that stores references -- it would just be a nasty surprise to anyone that thought it worked like a standard container.
EDIT: I know in this case, if it were an actual class i would be better off not putting the string on the heap. However, this is just a sample code to make sure i understand the theory. The actual code is going to be a red black tree, with all the nodes stored on the heap.
I want to make sure i have these basic ideas correct before moving on (I am coming from a Java/Python background). I have been searching the net, but haven't found a concrete answer to this question yet.
When you reassign a pointer to a new object, do you have to call delete on the old object first to avoid a memory leak? My intuition is telling me yes, but i want a concrete answer before moving on.
For example, let say you had a class that stored a pointer to a string
class MyClass
{
private:
std::string *str;
public:
MyClass (const std::string &_str)
{
str=new std::string(_str);
}
void ChangeString(const std::string &_str)
{
// I am wondering if this is correct?
delete str;
str = new std::string(_str)
/*
* or could you simply do it like:
* str = _str;
*/
}
....
In the ChangeString method, which would be correct?
I think i am getting hung up on if you dont use the new keyword for the second way, it will still compile and run like you expected. Does this just overwrite the data that this pointer points to? Or does it do something else?
Any advice would be greatly appricated :D
If you must deallocate the old instance and create another one, you should first make sure that creating the new object succeeds:
void reset(const std::string& str)
{
std::string* tmp = new std::string(str);
delete m_str;
m_str = tmp;
}
If you call delete first, and then creating a new one throws an exception, then the class instance will be left with a dangling pointer. E.g, your destructor might end up attempting to delete the pointer again (undefined behavior).
You could also avoid that by setting the pointer to NULL in-between, but the above way is still better: if resetting fails, the object will keep its original value.
As to the question in the code comment.
*str = _str;
This would be the correct thing to do. It is normal string assignment.
str = &_str;
This would be assigning pointers and completely wrong. You would leak the string instance previously pointed to by str. Even worse, it is quite likely that the string passed to the function isn't allocated with new in the first place (you shouldn't be mixing pointers to dynamically allocated and automatic objects). Furthermore, you might be storing the address of a string object whose lifetime ends with the function call (if the const reference is bound to a temporary).
Why do you think you need to store a pointer to a string in your class? Pointers to C++ collections such as string are actually very rarely necessary. Your class should almost certainly look like:
class MyClass
{
private:
std::string str;
public:
MyClass (const std::string & astr) : str( astr )
{
}
void ChangeString(const std::string & astr)
{
str = astr;
}
....
};
Just pinpointing here, but
str = _str;
would not compile (you're trying to assign _str, which is the value of a string passed by reference, to str, which is the address of a string). If you wanted to do that, you would write :
str = &_str;
(and you would have to change either _str or str so that the constnest matches).
But then, as your intuition told you, you would have leaked the memory of whatever string object was already pointed to by str.
As pointed earlier, when you add a variable to a class in C++, you must think of whether the variable is owned by the object, or by something else.
If it is owned by the object, than you're probably better off with storing it as a value, and copying stuff around (but then you need to make sure that copies don't happen in your back).
It is is not owned, then you can store it as a pointer, and you don't necessarily need to copy things all the time.
Other people will explain this better than me, because I am not really confortable with it.
What I end up doing a lot is writing code like this :
class Foo {
private :
Bar & dep_bar_;
Baz & dep_baz_;
Bing * p_bing_;
public:
Foo(Bar & dep_bar, Baz & dep_baz) : dep_bar_(dep_bar), dep_baz_(dep_baz) {
p_bing = new Bing(...);
}
~Foo() {
delete p_bing;
}
That is, if an object depends on something in the 'Java' / 'Ioc' sense (the objects exists elsewhere, you're not creating it, and you only wants to call method on it), I would store the dependency as a reference, using dep_xxxx.
If I create the object, I would use a pointer, with a p_ prefix.
This is just to make the code more "immediate". Not sure it helps.
Just my 2c.
Good luck with the memory mgt, you're right that it is the tricky part comming from Java ; don't write code until you're confortable, or you're going to spend hours chasing segaults.
Hoping this helps !
The general rule in C++ is that for every object created with "new" there must be a "delete". Making sure that always happens in the hard part ;) Modern C++ programmers avoid creating memory on the heap (i.e. with "new") like the plague and use stack objects instead. Really consider whether you need to be using "new" in your code. It's rarely needed.
If you're coming from a background with garbage collected languages and find yourself really needing to use heap memory, I suggest using the boost shared pointers. You use them like this:
#include <boost/shared_ptr.hpp>
...
boost::shared_ptr<MyClass> myPointer = boost::shared_ptr<MyClass>(new MyClass());
myPointer has pretty much the same language semantics as a regular pointer, but shared_ptr uses reference counting to determine when delete the object it's referencing. It's basically do it yourself garbage collection. The docs are here: http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm
I'll just write a class for you.
class A
{
Foo * foo; // private by default
public:
A(Foo * foo_): foo(foo_) {}
A(): foo(0) {} // in case you need a no-arguments ("default") constructor
A(const A &a):foo(new Foo(a.foo)) {} // this is tricky; explanation below
A& operator=(const &A a) { foo = new Foo(a.foo); return *this; }
void setFoo(Foo * foo_) { delete foo; foo = foo_; }
~A() { delete foo; }
}
For classes that hold resources like this, the copy constructor, assignment operator, and destructor are all necessary. The tricky part of the copy constructor and assignment operator is that you need to delete each Foo precisely once. If the copy constructor initializer had said :foo(a.foo), then that particular Foo would be deleted once when the object being initialized was destroyed and once when the object being initialized from (a) was destroyed.
The class, the way I've written it, needs to be documented as taking ownership of the Foo pointer it's being passed, because Foo * f = new Foo(); A a(f); delete f; will also cause double deletion.
Another way to do that would be to use Boost's smart pointers (which were the core of the next standard's smart pointers) and have boost::shared_ptr<Foo> foo; instead of Foo * f; in the class definition. In that case, the copy constructor should be A(const A &a):foo(a.foo) {}, since the smart pointer will take care of deleting the Foo when all the copies of the shared pointer pointing at it are destroyed. (There's problems you can get into here, too, particularly if you mix shared_ptr<>s with any other form of pointer, but if you stick to shared_ptr<> throughout you should be OK.)
Note: I'm writing this without running it through a compiler. I'm aiming for accuracy and good style (such as the use of initializers in constructors). If somebody finds a problem, please comment.
Three comments:
You need a destructor as well.
~MyClass()
{
delete str;
}
You really don't need to use heap allocated memory in this case. You could do the following:
class MyClass {
private:
std::string str;
public:
MyClass (const std::string &_str) {
str= _str;
}
void ChangeString(const std::string &_str) {
str = _str;
};
You can't do the commented out version. That would be a memory leak. Java takes care of that because it has garbage collection. C++ does not have that feature.
When you reassign a pointer to a new object, do you have to call delete on the old object first to avoid a memory leak? My intuition is telling me yes, but i want a concrete answer before moving on.
Yes. If it's a raw pointer, you must delete the old object first.
There are smart pointer classes that will do this for you when you assign a new value.
I have general question regarding the use of pointers vs. references in this particular scenario.
Let's say that I have a function that is going to do some computation and store the value inside an object for later use by the caller. I can implement this by using either pointers or references.
Although, I would prefer using references because I trying avoiding pointers as much as possible, are there any pros/cons of one approach over the other.
The code using Pointers would be as follows:
Node*& computeNode() {
// Do some computation before creating a node object.
Node* newNode = new Node;
newNode->member1 = xyz;
newNode->member2 = abc;
// and so on ...
return newNode;
}
The code using references could do something like this:
void computeNode(Node& newNode) {
// Do some computation before assigning values to the node object.
newNode.member1 = xyz;
newNode.member2 = abc;
// and so on.
}
The differences that I can see are as follows:
When using the pointer method, the newNode object is allocated on the Heap. So, unless I call delete on it, it is not going to get deleted. However, in the reference method, whether newNode is allocated on the Heap/Stack depends on what the caller did to create the newNode object.
Whenever we use references, the number of arguments needed to pass to the function increases by at least 1. This is fine, only I find it a bit counter-intuitive to pass the return object also to a function call unless I name the function in such a way that it becomes obvious to the API user.
By using references, I can simulate the return of multiple objects. In the pointer method, I think I will have to wrap all the objects in another structure (like a pair class) and then return it. That increases the overhead.
However, I do not know if usually one is preferred over the other. And if there are any function naming conventions in C++ that let the developer know that he is supposed to pass the return object also as an argument.
You could try returning an auto_ptr or shared_ptr. That would eliminate the issues with delete.
The second approach is probably preferable because there is no possibility of a memory leak, in the event you forget to delete the returned pointer.
It's usually good practice to code in such a way that each function or object which allocates heap memory also deallocates that memory. Your first example violates that practice, making it the function caller's responsibility to deallocate the memory. This makes memory leaks more likely, because now every time the function is called there is another opportunity to forget to delete the returned pointer.
You may also want to consider returning the object by value (which will return a copy of the object) in cases where the size of the object is not that large. Even though this will require a copy to be created, if the object is not so large it won't impact performance. (This method will become a lot more attractive in the future with C++0x move semantics.)
I think your first option should be returning by value (or perhaps make the constructor compute the members?):
Node computeNode()
{
Node n;
n.x = abc;
n.y = xyz;
return n;
}
This may look inefficient, but it is quite possible that copying is elided with NRVO.
If the Node needs to be dynamically allocated anyway, you should return the pointer by value (a copy of the pointer):
Node* computeNode();
Otherwise you will be returning a reference to a local variable (pointer).
I prefer using the second approach to send back information (as you said, allows for multiple "returns" without using an extra structure) and generally return an error or a success code.
Also, I set the purely input arguments as const & to distinguish between the input and output variables.
You can return by value and avoid copies in some situations, by using const references like this :
Node computeNode() {
// Do some computation before creating a node object.
Node newNode;
newNode.member1 = xyz;
newNode.member2 = abc;
return newNode;
}
const Node &n = computeNode();
The lifetime of the temporary object in computeNode is extended upto the scope of the reference n
If the alternatives are really as given, it’s not clear why you need a reference/pointer at all; you could also just return by value:
Node computeNode() {
// Do some computation before creating a node object.
Node newNode;
newNode.member1 = xyz;
newNode.member2 = abc;
return newNode;
}
Despite what many people think, this isn’t actually very inefficient because the compiler can (and will!) elide most of the unnecessary copies.
Semantically, this is the solution that you want, unless the node gets stored somewhere else as well and you need to preserve reference identity.