Jul 1, 2013 at 3:15am UTC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
struct A
{
~A() { std::cout << 'A' ; }
};
int main()
{
std::vector<A*> v(4, static_cast <A*>(0));
v[0] = new A;
v[1] = new A;
v[2] = new A;
v[3] = new A;
std::for_each(v.begin(), v.end(), std::ptr_fun(&::operator delete ));
std::cout << std::endl;
return 0;
}
This program does not print 'A'-s from the destructor. Any idea why?
A heads up related to deleting pointers in vector. I know several ways to do it, just wondering why this way it does not work. Checked with g++ 4.4.3 on Ubuntu 10.
Thanks!
Last edited on Jul 1, 2013 at 11:29am UTC
Jul 1, 2013 at 4:00am UTC
I find for_each to be obfuscated in pretty much every situation I've ever seen it in.
You're much better off with a range based for loop here:
1 2
for (auto & i : v)
delete i;
Much shorter, much simpler, much more clear. Of course for this to work you have to make A's dtor public.
Plus I'm pretty sure ptr_fun is deprecated as of C++11.
EDIT: also, of course, if you're using smart pointers, you don't have to
delete
anything.
EDIT 2:
And to answer your actual question...
operator delete
is different from regular
delete
.
regular delete calls dtors and frees memory.
operator delete only frees memory.
Try this:
operator delete (v[0]); // does not call dtor
Last edited on Jul 1, 2013 at 4:04am UTC
Jul 1, 2013 at 4:48am UTC
You are calling
funcion operator delete that all what it does is reclaims the storage allocated by the earlier call to operator new.
There is C++ operator delete and there is function operator delete in C++. The function is called by operator delete and can be redefined by the user.
Consider the difference between these code snips
1 2 3 4 5 6 7 8
struct A
{
~A() { std::cout << "A::~A()\n" ; }
};
A *p = new A();
::delete ( p );
Here the operator delete is called that at first calls the class destructor and after that it calls function operator delete..
1 2 3 4 5 6 7 8
struct A
{
~A() { std::cout << "A::~A()\n" ; }
};
A *p = new A();
::operator delete ( p );
Here
function operator delete is called. It only reclaims the storage.
That to do what you want you can use a lambda expression
std::for_each(v.begin(), v.end(), []( A *p ) { ::delete p; } );
Or you can write the corresponding functional object yourself.
Last edited on Jul 1, 2013 at 4:52am UTC
Jul 1, 2013 at 11:39am UTC
Disch, Vlad,
Thank you for pointing out the difference between operator delete and function operator delete.
One more question: is it possible to get the pointer to the operator delete (::delete) in order to compile this snip?
std::for_each(v.begin(), v.end(), std::ptr_fun(&::delete ));
I don't want to use C++11 yet.
Thanks!
P.S. I changed class to struct in my original code.
Last edited on Jul 1, 2013 at 11:40am UTC
Jul 1, 2013 at 12:37pm UTC
It may be best to forget ptr_fun() and put your own function in that does the delete. Sometimes the obvious ways are best, especially for maintenance by someone else.
Jul 1, 2013 at 12:41pm UTC
if you provide a null to delete, it does nothing
Jul 1, 2013 at 10:38pm UTC
is it possible to get the pointer to the operator delete
No.
Andy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct A {
A() { std::cout << "A::A()\n" ; }
~A() { std::cout << "A::~A()\n" ; }
};
// as deleter is templated, it must be declared outide function scope
template <typename T>
struct deleter {
void operator ()(T* ptr) {
delete ptr;
}
};
// or use a function (templated or otherwise, they
// need to be declared at global/namespace scope)
//
// template<typename T>
// void deleter(A* ptr) {
// delete ptr;
// }
//
// call like:
// std::for_each(v.begin(), v.end(), deleter<A>);
int main() {
//std::vector<A*> v(4, static_cast<A*>(0));
//
// static_cast<A*>(0) not needed as zeroing handled by default param
// provided, e.g. const value_type& val = value_type()
//
std::vector<A*> v(4);
// not templated, so ok at function scope
struct newer {
A* operator ()() {
return new A;
}
};
std::generate(v.begin(), v.end(), newer());
std::cout << std::endl;
std::for_each(v.begin(), v.end(), deleter<A>());
std::cout << std::endl;
return 0;
}
Output:
A::A()
A::A()
A::A()
A::A()
A::~A()
A::~A()
A::~A()
A::~A()
Last edited on Jul 2, 2013 at 12:23am UTC
Jul 2, 2013 at 12:13am UTC
C++11 actually has that functor already, in header <memory>
std::for_each(v.begin(), v.end(), std::default_delete<A>());