If I have a list<object*>>* queue and want to pop the first object in the list and hand it over to another part of the program, is it correct to use (sketchy code):
object* objPtr = queue->first();
queue->pop_first();
return objPtr; // is this a pointer to a valid memory address now?
?
According to the documentation on http://www.cplusplus.com/reference/stl/list/pop_front/ it calls the destructor of the deleted element, but I'm confused as to whether it means the linked list's node object, or the actually stored "user" object.
Edit: I might be front instead of first, my bad.
Yes, it is a valid pointer. List will not release the memory allocated by you. List will destroy its internal not the user object.
Yes it's valid: Since you put pointers into the list, only the pointer gets destroyed, not the object itself.
Yes objPtr contains pointer to a valid memory.
When you insert an element into a std::list, list makes a copy of it. In your case the element is an address (a pointer) so list makes a copy of the address and stores it.
object * optr = queue->pop_front();
optr now points to the object
queue->pop_front();
removes the element (an address/pointer) from the list, optr already points to your object.
After you're done with the object don't forget do delete it otherwise you end up with memory leak.
Example:
#include <iostream>
#include <list>
using namespace std;
struct A
{
static int count;
A() : val(count++) { cout << "A(" << val << ")" << endl; }
~A() { cout << "~A(" << val << ")" << endl; }
int val;
};
int A::count = 0;
ostream& operator<<(ostream& os, A& a) { return os << a.val; }
int main()
{
list<A*> alist;
for (unsigned int i = 3; i; --i) alist.push_back(new A());
for (unsigned int i = 3; i; --i)
{
A * aptr = alist.front();
alist.pop_front();
cout << *aptr << endl;
delete aptr;
aptr = 0;
}
}
The standard indeed says (23.2.2.3/5) that the destructor of the element's type is called. But this type is a pointer here, and the destructor of a pointer does nothing...
Your code is well but it is better to use list< boost::shared_ptr<object> >.
shared_ptr < object> objPtr = queue->first();
queue->pop_first();
return objPtr;
When you remove the elements, STL containers will not destroy the user objects allocated on heap.
class A
{
};
list<A*> PointerToObjectList;
A* ptr = new A();
PointerToObjectList.push_back(ptr);
If you remove the ptr from the list, list will not delete the object automatically. You need to explicitly call delete once the object is no longer being used.
Related
Under which circumstances would you want to use code of this nature in c++?
void foo(type *&in) {...}
void fii() {
type *choochoo;
...
foo(choochoo);
}
You would want to pass a pointer by reference if you have a need to modify the pointer rather than the object that the pointer is pointing to.
This is similar to why double pointers are used; using a reference to a pointer is slightly safer than using pointers.
50% of C++ programmers like to set their pointers to null after a delete:
template<typename T>
void moronic_delete(T*& p)
{
delete p;
p = nullptr;
}
Without the reference, you would only be changing a local copy of the pointer, not affecting the caller.
David's answer is correct, but if it's still a little abstract, here are two examples:
You might want to zero all freed pointers to catch memory problems earlier. C-style you'd do:
void freeAndZero(void** ptr)
{
free(*ptr);
*ptr = 0;
}
void* ptr = malloc(...);
...
freeAndZero(&ptr);
In C++ to do the same, you might do:
template<class T> void freeAndZero(T* &ptr)
{
delete ptr;
ptr = 0;
}
int* ptr = new int;
...
freeAndZero(ptr);
When dealing with linked-lists - often simply represented as pointers to a next node:
struct Node
{
value_t value;
Node* next;
};
In this case, when you insert to the empty list you necessarily must change the incoming pointer because the result is not the NULL pointer anymore. This is a case where you modify an external pointer from a function, so it would have a reference to pointer in its signature:
void insert(Node* &list)
{
...
if(!list) list = new Node(...);
...
}
There's an example in this question.
I have had to use code like this to provide functions to allocate memory to a pointer passed in and return its size because my company "object" to me using the STL
int iSizeOfArray(int* &piArray) {
piArray = new int[iNumberOfElements];
...
return iNumberOfElements;
}
It is not nice, but the pointer must be passed by reference (or use double pointer). If not, memory is allocated to a local copy of the pointer if it is passed by value which results in a memory leak.
One example is when you write a parser function and pass it a source pointer to read from, if the function is supposed to push that pointer forward behind the last character which has been correctly recognized by the parser. Using a reference to a pointer makes it clear then that the function will move the original pointer to update its position.
In general, you use references to pointers if you want to pass a pointer to a function and let it move that original pointer to some other position instead of just moving a copy of it without affecting the original.
Another situation when you may need this is if you have stl collection of pointers and want to change
them using stl algorithm. Example of for_each in c++98.
struct Storage {
typedef std::list<Object*> ObjectList;
ObjectList objects;
void change() {
typedef void (*ChangeFunctionType)(Object*&);
std::for_each<ObjectList::iterator, ChangeFunctionType>
(objects.begin(), objects.end(), &Storage::changeObject);
}
static void changeObject(Object*& item) {
delete item;
item = 0;
if (someCondition) item = new Object();
}
};
Otherwise, if you use changeObject(Object* item) signature you have copy of pointer, not original one.
Refer the code below:
When we pass x as Node *x, a new variable is created with the same address passed on by the caller function.
If you modify the value pointed by the pointer, that change will be reflected in the caller function variable.
But if we change the value of the pointer itself it will not be reflected in the caller function because callee function has the copy of the passed pointer not the original pointer itself.
void increment(int *x) {
(*x)++;
x++;
cout << x << endl; // prints 0x7ffe9f8e1900
}
int main() {
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints 11
cout << x << endl; // prints 0x7ffe9f8e18fc
return 0;
}
Now, check the below code:
When we pass x as Node *&x, we pass a reference of the original variable present in the caller function meaning these two variable (caller and callee root) are same, their name may differ.
if we modify the value pointer by the pointer, that change will be reflected in the caller function variable.
Now if we change the value of the pointer itself it will also be reflected in the caller function variable.
void increment(int* &x)
{
(*x) ++;
cout << *x << endl; // prints 11
x++;
cout << x << endl; // prints 0x7fffb93eba70
}
int main()
{
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints garbage
cout << x << endl; // prints 0x7fffb93eba70
return 0;
}
I have an object O1 which has pointer. I created another object O2 by copy constructor. The pointer address will be copied into the object O2. When i come out of scope of O2, it will be deleted. The destructor will delete the pointer as well. This make the pointers in object O1 become dangling. How to make sure that i delete the pointer only when i come out of O1.
In a short description, how to delete the object pointer only when no others are referring to that pointer directly or indirectly.
class info {
public:
char *buf;
int len;
info(int l) {
len = l;
buf = new char[len];
buf[0] = 'h';
}
~info() {
delete[] buf;
}
};
int main() {
info O1(100);
cout << O1.buf << "\n";
{
info O2(O1);
}
cout << O1.buf << "\n";
}
Here the destructor of O1 at the end of the main will get a SIGABT signal for trying to deallocate a memory referred by O1.buf which is already deleted through O2.
Shared pointers are exactly what you need.
I also suggest you have a look at the other smart pointers available in the memory standard library.
Edit:
Note that as explained here you should use delete[] as a destructor for your smart pointers that own an array type.
To be specific about shared_ptr usage, the class info should be:
class info {
public:
std::shared_ptr<char> buf;
int len;
info(int l) {
len = l;
if(!buf) buf = std::shared_ptr<char>(new char[len], std::default_delete<char[]>());
buf.get()[0] = 'h';
}
~info() {
}
};
int main() {
info O1(100);
cout << O1.buf << "\n";
{
info O2(O1);
}
cout << O1.buf.get() << "\n";
}
It seems that what you need are shared pointers. They are a bit tricky to use for arrays, this answer tells how to.
Under which circumstances would you want to use code of this nature in c++?
void foo(type *&in) {...}
void fii() {
type *choochoo;
...
foo(choochoo);
}
You would want to pass a pointer by reference if you have a need to modify the pointer rather than the object that the pointer is pointing to.
This is similar to why double pointers are used; using a reference to a pointer is slightly safer than using pointers.
50% of C++ programmers like to set their pointers to null after a delete:
template<typename T>
void moronic_delete(T*& p)
{
delete p;
p = nullptr;
}
Without the reference, you would only be changing a local copy of the pointer, not affecting the caller.
David's answer is correct, but if it's still a little abstract, here are two examples:
You might want to zero all freed pointers to catch memory problems earlier. C-style you'd do:
void freeAndZero(void** ptr)
{
free(*ptr);
*ptr = 0;
}
void* ptr = malloc(...);
...
freeAndZero(&ptr);
In C++ to do the same, you might do:
template<class T> void freeAndZero(T* &ptr)
{
delete ptr;
ptr = 0;
}
int* ptr = new int;
...
freeAndZero(ptr);
When dealing with linked-lists - often simply represented as pointers to a next node:
struct Node
{
value_t value;
Node* next;
};
In this case, when you insert to the empty list you necessarily must change the incoming pointer because the result is not the NULL pointer anymore. This is a case where you modify an external pointer from a function, so it would have a reference to pointer in its signature:
void insert(Node* &list)
{
...
if(!list) list = new Node(...);
...
}
There's an example in this question.
I have had to use code like this to provide functions to allocate memory to a pointer passed in and return its size because my company "object" to me using the STL
int iSizeOfArray(int* &piArray) {
piArray = new int[iNumberOfElements];
...
return iNumberOfElements;
}
It is not nice, but the pointer must be passed by reference (or use double pointer). If not, memory is allocated to a local copy of the pointer if it is passed by value which results in a memory leak.
One example is when you write a parser function and pass it a source pointer to read from, if the function is supposed to push that pointer forward behind the last character which has been correctly recognized by the parser. Using a reference to a pointer makes it clear then that the function will move the original pointer to update its position.
In general, you use references to pointers if you want to pass a pointer to a function and let it move that original pointer to some other position instead of just moving a copy of it without affecting the original.
Another situation when you may need this is if you have stl collection of pointers and want to change
them using stl algorithm. Example of for_each in c++98.
struct Storage {
typedef std::list<Object*> ObjectList;
ObjectList objects;
void change() {
typedef void (*ChangeFunctionType)(Object*&);
std::for_each<ObjectList::iterator, ChangeFunctionType>
(objects.begin(), objects.end(), &Storage::changeObject);
}
static void changeObject(Object*& item) {
delete item;
item = 0;
if (someCondition) item = new Object();
}
};
Otherwise, if you use changeObject(Object* item) signature you have copy of pointer, not original one.
Refer the code below:
When we pass x as Node *x, a new variable is created with the same address passed on by the caller function.
If you modify the value pointed by the pointer, that change will be reflected in the caller function variable.
But if we change the value of the pointer itself it will not be reflected in the caller function because callee function has the copy of the passed pointer not the original pointer itself.
void increment(int *x) {
(*x)++;
x++;
cout << x << endl; // prints 0x7ffe9f8e1900
}
int main() {
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints 11
cout << x << endl; // prints 0x7ffe9f8e18fc
return 0;
}
Now, check the below code:
When we pass x as Node *&x, we pass a reference of the original variable present in the caller function meaning these two variable (caller and callee root) are same, their name may differ.
if we modify the value pointer by the pointer, that change will be reflected in the caller function variable.
Now if we change the value of the pointer itself it will also be reflected in the caller function variable.
void increment(int* &x)
{
(*x) ++;
cout << *x << endl; // prints 11
x++;
cout << x << endl; // prints 0x7fffb93eba70
}
int main()
{
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints garbage
cout << x << endl; // prints 0x7fffb93eba70
return 0;
}
Ignoring usefulness of such practice. (Though real-life examples are welcome, of course.)
For example, the following program outputs the correct value for a:
#include <iostream>
using namespace std;
int main()
{
int a = 11111;
int i = 30;
int* pi = new (&i) int();
cout << a << " " << endl;
}
But isn't new-allocation supposed to create some bookkeeping information adjacent to i (for correct subsequent deallocation), which in this case is supposed to corrupt the stack around i?
Yes, it's perfectly OK to perform placement-new with a pointer to an object on the stack. It will just use that specific pointer to construct the object in. Placement-new isn't actually allocating any memory - you have already provided that part. It only does construction. The subsequent deletion won't actually be delete - there is no placement delete - since all you need to do is call the object's destructor. The actual memory is managed by something else - in this case your stack object.
For example, given this simple type:
struct A {
A(int i)
: i(i)
{
std::cout << "make an A\n";
}
~A() {
std::cout << "delete an A\n";
}
int i;
};
The following is completely reasonable, well-behaved code:
char buf[] = {'x', 'x', 'x', 'x', 0};
std::cout << buf << std::endl; // xxxx
auto a = new (buf) A{'a'}; // make an A
std::cout << a->i << std::endl; // 97
a->~A(); // delete an A
The only case where this would be invalid would be if your placement-new-ed object outlasts the memory you new-ed it on - for the same reason that returning a dangling pointer is always bad:
A* getAnA(int i) {
char buf[4];
return new (buf) A(5); // oops
}
Placement new constructs the element in place and does not allocate memory.
The "bookkeeping information" in this case is the returned pointer which ought to be used to destroy the placed object.
There is no delete associated with the placement since placement is a construction. Thus, the required "clean up" operation for placement new is destruction.
The "usual steps" are
'Allocate' memory
Construct element(s) in place
Do stuff
Destroy element(s) (reverse of 2)
'Deallocate' memory (reverse of 1)
(Where memory can be stack memory which is neither required to be explicitly allocated nor deallocated but comes and goes with a stack array or object.)
Note: If "placing" an object into memory of the same type on the stack one should keep in mind that there's automatic destruction at the end of the object's lifetime.
{
X a;
a.~X(); // destroy a
X * b = new (&a) X(); // Place new X
b->~X(); // destroy b
} // double destruction
No, because you don't delete an object which has been placement-newed, you call its destructor manually.
struct A {
A() { std::cout << "A()\n"; }
~A() { std::cout << "~A()\n"; }
};
int main()
{
alignas(A) char storage[sizeof(A)];
A *a = new (storage) A;
std::cout << "hi!\n";
a->~A();
std::cout << "bye!\n";
}
Output:
A()
hi!
~A()
bye!
In your case, there's no need to call a destructor either, because int is trivially-destructible, meaning that its destructor would be a no-op anyway.
Beware though not to invoke placement-new on an object that is still alive, because not only will you corrupt its state, but its destructor will also be invoked twice (once when you call it manually, but also when the original object should have been deleted, for exampel at the end of its scope).
Placement new does construction, not allocation, so there's no bookkeeping information to be afraid of.
I can at the moment think of one possible use case, though it (in this form) would be a bad example of encapsulation:
#include <iostream>
using namespace std;
struct Thing {
Thing (int value) {
cout << "such an awesome " << value << endl;
}
};
union Union {
Union (){}
Thing thing;
};
int main (int, char **) {
Union u;
bool yes;
cin >> yes;
if (yes) {
new (&(u.thing)) Thing(42);
}
return 0;
}
Live here
Though even when the placement new is hidden in some member function, the construction still happens on the stack.
So: I didn't look in the standard, but can't think of why placement new on the stack shouldn't be permitted.
A real world example should be somewhere in the source of https://github.com/beark/ftl ... in their recursive union, which is used for the sum type.
Under which circumstances would you want to use code of this nature in c++?
void foo(type *&in) {...}
void fii() {
type *choochoo;
...
foo(choochoo);
}
You would want to pass a pointer by reference if you have a need to modify the pointer rather than the object that the pointer is pointing to.
This is similar to why double pointers are used; using a reference to a pointer is slightly safer than using pointers.
50% of C++ programmers like to set their pointers to null after a delete:
template<typename T>
void moronic_delete(T*& p)
{
delete p;
p = nullptr;
}
Without the reference, you would only be changing a local copy of the pointer, not affecting the caller.
David's answer is correct, but if it's still a little abstract, here are two examples:
You might want to zero all freed pointers to catch memory problems earlier. C-style you'd do:
void freeAndZero(void** ptr)
{
free(*ptr);
*ptr = 0;
}
void* ptr = malloc(...);
...
freeAndZero(&ptr);
In C++ to do the same, you might do:
template<class T> void freeAndZero(T* &ptr)
{
delete ptr;
ptr = 0;
}
int* ptr = new int;
...
freeAndZero(ptr);
When dealing with linked-lists - often simply represented as pointers to a next node:
struct Node
{
value_t value;
Node* next;
};
In this case, when you insert to the empty list you necessarily must change the incoming pointer because the result is not the NULL pointer anymore. This is a case where you modify an external pointer from a function, so it would have a reference to pointer in its signature:
void insert(Node* &list)
{
...
if(!list) list = new Node(...);
...
}
There's an example in this question.
I have had to use code like this to provide functions to allocate memory to a pointer passed in and return its size because my company "object" to me using the STL
int iSizeOfArray(int* &piArray) {
piArray = new int[iNumberOfElements];
...
return iNumberOfElements;
}
It is not nice, but the pointer must be passed by reference (or use double pointer). If not, memory is allocated to a local copy of the pointer if it is passed by value which results in a memory leak.
One example is when you write a parser function and pass it a source pointer to read from, if the function is supposed to push that pointer forward behind the last character which has been correctly recognized by the parser. Using a reference to a pointer makes it clear then that the function will move the original pointer to update its position.
In general, you use references to pointers if you want to pass a pointer to a function and let it move that original pointer to some other position instead of just moving a copy of it without affecting the original.
Another situation when you may need this is if you have stl collection of pointers and want to change
them using stl algorithm. Example of for_each in c++98.
struct Storage {
typedef std::list<Object*> ObjectList;
ObjectList objects;
void change() {
typedef void (*ChangeFunctionType)(Object*&);
std::for_each<ObjectList::iterator, ChangeFunctionType>
(objects.begin(), objects.end(), &Storage::changeObject);
}
static void changeObject(Object*& item) {
delete item;
item = 0;
if (someCondition) item = new Object();
}
};
Otherwise, if you use changeObject(Object* item) signature you have copy of pointer, not original one.
Refer the code below:
When we pass x as Node *x, a new variable is created with the same address passed on by the caller function.
If you modify the value pointed by the pointer, that change will be reflected in the caller function variable.
But if we change the value of the pointer itself it will not be reflected in the caller function because callee function has the copy of the passed pointer not the original pointer itself.
void increment(int *x) {
(*x)++;
x++;
cout << x << endl; // prints 0x7ffe9f8e1900
}
int main() {
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints 11
cout << x << endl; // prints 0x7ffe9f8e18fc
return 0;
}
Now, check the below code:
When we pass x as Node *&x, we pass a reference of the original variable present in the caller function meaning these two variable (caller and callee root) are same, their name may differ.
if we modify the value pointer by the pointer, that change will be reflected in the caller function variable.
Now if we change the value of the pointer itself it will also be reflected in the caller function variable.
void increment(int* &x)
{
(*x) ++;
cout << *x << endl; // prints 11
x++;
cout << x << endl; // prints 0x7fffb93eba70
}
int main()
{
int a = 10;
int *x = &a;
increment(x);
cout << *x << endl; // prints garbage
cout << x << endl; // prints 0x7fffb93eba70
return 0;
}