C++ std::sort() Calling Destructor - c++

I overloaded my class' () operator to use it as a sort comparer function. When using std::sort(), it for some reason calls the the class' destructor a bunch of times (dependant on the amount of entries in the vector, apparently). I've described more in ~RANK().
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
class RANK
{
struct COMBO
{
int x;
};
std::vector<COMBO *> data;
public:
RANK()
{
printf("RANK()\n");
}
~RANK()
{
printf("~RANK()\n");
/*
* Here is the problem.
* Since my vector consists of pointers to COMBO objects,
* I delete them upon RANK object's destruction. However,
* std::sort() calls RANK's destructor many times and
* throws some runtime error, unless commented out.
*/
//for (unsigned int i = 0, n = data.size(); i < n; i++)
// delete data[i];
}
void Add(int x)
{
COMBO *combo = new COMBO();
combo->x = x;
data.push_back(combo);
}
unsigned int Size()
{
return data.size();
}
void Sort()
{
std::sort(data.begin(), data.end(), *this);
}
int operator[](unsigned int pos)
{
return data[pos]->x;
}
bool operator()(COMBO *combo1, COMBO *combo2)
{
return combo1->x > combo2->x;
}
};
int main()
{
RANK rank;
rank.Add(1337);
rank.Add(9001);
rank.Sort();
for (unsigned int i = 0, n = rank.Size(); i < n; i++)
printf("%d ", rank[i]);
printf("\n");
system("pause");
return 0;
}
The output (with commented destructor):
RANK()
~RANK()
~RANK()
~RANK()
~RANK()
~RANK()
9001 1337

The comparison function to std::sort is passed by value. By using the RANK object as the comparator, you are passing a copy to std::sort (as the last value) and it may copy it more than once internally.
I would suggest separating out the comparison operator for COMBO from the class RANK

The first problem is that you're breaking the Rule of Three. Your class requires a non-trivial destructor to release its resources, so it needs to be either correctly copyable or uncopyable to avoid multiple objects owning the same resources. The simplest solution is to prevent copying by deleting the copy constructor and copy-assignment operator:
RANK(RANK const &) = delete;
void operator=(RANK const &) = delete;
or, if you're stuck with a pre-2011 compiler, declare them private with no implementation.
Alternatively, you could consider storing smart pointers such as std::unique_ptr (to prevent copying) or std::shared_ptr (to allow shared ownership); if you do that, then your class will have the same (safe) copy semantics as the pointer you choose.
Preventing copying will make the second problem obvious: you're using the RANK object as the comparator for std::sort. The comparator is taken by value, so the object is copied there. That's easy to fix by defining a separate type for the comparator:
struct CompareCOMBO {
bool operator()(COMBO *combo1, COMBO *combo2) {
return combol1->x > combo2->x;
}
};
std::sort(data.begin(), data.end(), CompareCOMBO());
or, if you can use lambdas:
std::sort(data.begin(), data.end(),
[](COMBO *combo1, COMBO *combo2){
return combo1->x > combo2->x;
}
);

Provide a copy constructor and place a breakpoint inside to see where it is called.

By passing *this as your compare object it gets copied during the sort (that's why you don't see the construction popping, if you had a copy constructor you would see calls to that).
Consider this thread to sort your objects

Related

Allocating an array of a class c++

How would I go about allocating an array of a class without constructing the class, so I could fill up the array later?
I was originally trying to use
Myclass * array = new Myclass[N];
But it tries to construct Myclass to N.
First just declare it without allocating
Myclass * array[N];
when you need it
for(int i=0;i<N;i++){
array[i] = new Myclass(/*params*/);
}
But consider using std::vector/std::list if you must not have to manage memory yourself.
If you really want to do that, (not sure why), you could try
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass()
{ cout << "helo" << endl; }
};
int main(int argc, char *argv[])
{
int size = 4;
// Here is the trick, pointer to pointer.
MyClass **vec = new MyClass *[size];
cout << "before" << endl;
for (int i = 0; i < 4; ++i)
vec[i] = new MyClass;
// remember to free the vec
return 0;
}
Someone suggested placement new, so here it goes:
// allocate space
std::vector<unsigned char> mybuffer(N * sizeof(Myclass));
Myclass *array = reinterpret_cast<Myclass *>(&mybuffer[0]);
// when you're ready to use it
new( &array[0] ) Myclass(2);
new( &array[1] ) Myclass(3);
// etc...
// when you're done with it
array[0].~Myclass();
array[1].~Myclass();
// etc....
Of course, it is undefined behaviour to use array[x] before you have new'd it, or after you called the destructor.
This is generally something you wouldn't use as a solution to a "normal" problem. Consider actually defining a default constructor that does nothing, and having a function you call later which enhances the objects above their default state.
If you can use C++11, the optimal solution for you is probably std::vector<MyClass> with emplace-base insertions:
class MyClass {
public:
MyClass(int a, bool b, char c); // some non-default constructor
MyClass(double d); // another constructor
void bar();
};
void foo(int n) {
std::vector<MyClass> mv;
mv.reserve(n); // not even needed but beneficial if you know the final size.
// emplace_back uses perfect forwarding to call any arbitrary constructor:
mv.emplace_back(2, false, 'a');
mv.emplace_back(3, true, 'b');
mv.emplace_back(3.1415926535);
// can iterate vector easily:
for (auto &i : mv) {
i.bar();
}
// everything destructed automatically when the collection falls of scope ...
}
This creates the values in the collection directly without a copy and defers any construction of elements until you are ready, unlike new[], which makes a bunch of default objects at array-creation time. It is generally better than placement new as well, since it doesn't leave open opportunities for missed destruction or destructing an invalid memory location as well as being just easier to read.
Alternatively, you may use boost::optional.
So in your case:
std::vector<boost::optional<Myclass>> array(N);

Get Element Position within std::vector

How do I get the position of an element inside a vector, where the elements are classes. Is there a way of doing this?
Example code:
class Object
{
public:
void Destroy()
{
// run some code to get remove self from vector
}
}
In main.cpp:
std::vector<Object> objects;
objects.push_back( <some instances of Object> );
// Some more code pushing back some more stuff
int n = 20;
objects.at(n).Destroy(); // Assuming I pushed back 20 items or more
So I guess I want to be able to write a method or something which is a member of the class which will return the location of itself inside the vector... Is this possible?
EDIT:
Due to confusion, I should explain better.
void Destroy(std::vector<Object>& container){
container.erase( ?...? );
}
The problem is, how can I find the number to do the erasing...? Apparently this isn't possible... I thought it might not be...
You can use std::find to find elements in vector (providing you implement a comparison operator (==) for Object. However, 2 big concerns:
If you need to find elements in a container then you will ger much better performance with using an ordered container such as std::map or std::set (find operations in O(log(N)) vs O(N)
Object should not be the one responsible of removing itself from the container. Object shouldn't know or be concerned with where it is, as that breaks encapsulation. Instead, the owner of the container should concern itself ith such tasks.
The object can erase itself thusly:
void Destroy(std::vector<Object>& container);
{
container.erase(container.begin() + (this - &container[0]));
}
This will work as you expect, but it strikes me as exceptionally bad design. Members should not have knowledge of their containers. They should exist (from their own perspective) in an unidentifiable limbo. Creation and destruction should be left to their creator.
Objects in a vector don't automatically know where they are in the vector.
You could supply each object with that information, but much easier: remove the object from the vector. Its destructor is then run automatically.
Then the objects can be used also in other containers.
Example:
#include <algorithm>
#include <iostream>
#include <vector>
class object_t
{
private:
int id_;
public:
int id() const { return id_; }
~object_t() {}
explicit object_t( int const id ): id_( id ) {}
};
int main()
{
using namespace std;
vector<object_t> objects;
for( int i = 0; i <= 33; ++i )
{
objects.emplace_back( i );
}
int const n = 20;
objects.erase( objects.begin() + n );
for( auto const& o : objects )
{
cout << o.id() << ' ';
}
cout << endl;
}
If you need to destroy the n'th item in a vector then the easiest way is to get an iterator from the beginning using std::begin() and call std::advance() to advance how ever many places you want, so something like:
std::vector<Object> objects;
const size_t n = 20;
auto erase_iter = std::advance(std::begin(objects), n);
objects.erase(erase_iter);
If you want to find the index of an item in a vector then use std::find to get the iterator and call std::distance from the beginning.
So something like:
Object object_to_find;
std::vector<Object> objects;
auto object_iter = std::find(std::begin(objects), std::end(objects), object_to_find);
const size_t n = std::distance(std::begin(objects), object_iter);
This does mean that you need to implement an equality operator for your object. Or you could try something like:
auto object_iter = std::find(std::begin(objects), std::end(objects),
[&object_to_find](const Object& object) -> bool { return &object_to_find == &object; });
Although for this to work the object_to_find needs to be the one from the actual list as it is just comparing addresses.

Two operators simultaneity overload in c++

I want to represent my object like an array. I mean that the programmer can write in his code
myobject[3]=2
In the back (in myobject code) there isn't an array at all, it's only representation.
So I need to overload [] and = simultaneously.
How can this be done?
thank you,
and sorry about my poor English.
operator[] should return a reference to object you are trying to modify. It may be some kind of metaobject, that overloads operator= to do whatever you wish with your main object.
Edit: As the OP clarified the problem, there is a way to do this. Look here:
#include <vector>
#include <iostream>
int & func(std::vector<int> & a)
{
return a[3];
}
int main()
{
std::vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(4);
func(a) = 111;
std::cout << a[3] << std::endl;
}
So I need to overload [] and = simultaneity. How can it's can be done?
It can't be done. What you can do instead is override operator[] to return a 'proxy reference'. That is, an object that has knowledge of the object 'myobject' to which it was applied and the index used '3', and provides appropiate conversion operators to the mapped type (I pressume int) as well as assignment operators. There are a few examples of proxy references in the standard library itself. Something in the lines of:
class proxy
{
public:
proxy( object& object, int index ) : _object( object ), _index( index ) {}
operator int() const { return _object.implementation.value_at( index ); }
proxy operator=( int value ){ _object.implementation.value_at( index, value ); return *this; }
private:
object& _object;
int _index;
};
#yoni: It is possible to give address of any member of the vector (as long as it exists). Here's how it's done.
int& MyObject::operator[](size_t index)
{
return mVector[index];
}
const int& MyObject::operator[](size_t index) const
{
return mVector[index];
}
This is possible because std::vector is guaranteed to be storing elements in a contiguous array. The operator[] of std::vector returns a reference-type of the value it stores. By you overloading the operator[], you just need to pass that reference out of your operator[] function.
NOTE: std::vector will take care of bounds check. With the solution that #Griwes gives, there's no bounds checking.
EDIT: Seems like Griwes has edited his solution.

Am I Deleting my struct Properly?

This is a homework assignment. The Field container was the assignment from a week ago, and now I'm supposed to use the Field container to act as a dynamic array for a struct NumPair which holds two char * like so:
struct NumPair
{
char *pFirst, *pSecond;
int count;
NumPair( char *pfirst = "", char *psecond = "", int count = 0)
: pFirst(strdup(pfirst)), pSecond(strdup(psecond)), count(count)
{ }
NumPair( const NumPair& np )
: count(np.count), pFirst(strdup(np.pFirst)), pSecond(strdup(np.pSecond))
{ }
NumPair& operator=( const NumPair& np )
{
if(this != &np)
{
pFirst = strdup(np.pFirst);
pSecond = strdup(np.pSecond);
count = np.count;
}
return *this;
}
and the Field container
Field<NumPair> dict_;
The homework requires the use of char *, and not string, so that we can get better with all this low-level stuff. I've already had some question about char to wchar_t conversions, etc.
Now I have a question as to whether or not I'm destructing the NumPair properly. The scenario is as follows:
1) Field destructor gets called
template <class T>
Field<T>::~Field()
{
delete[] v_;
}
2) Delete calls the destructor of every element NumPair in v_;
~NumPair()
{
free(pFirst);
free(pSecond);
}
Is this okay? I haven't really read too many articles about mixing and matching elements created on the heap and free-store as we wish. I figure as long as I don't use delete on an improper malloc'ed element, I should be fine.
However, I don't know the entire intricacies of the delete command, so I'm wondering whether or not this is valid design, and what I could do to make it better.
Also, of course this isn't. I'm getting an error of the type:
This may be due to a corruption of the heap and points to dbgheap
extern "C" _CRTIMP int __cdecl _CrtIsValidHeapPointer(
const void * pUserData
)
{
if (!pUserData)
return FALSE;
if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
return FALSE;
return HeapValidate( _crtheap, 0, pHdr(pUserData) ); // Here
}
Again, how could I improve this without the use of string?
FIELD CTOR/Copy Ctor/Assignment
template <class T>
Field<T>::Field()
: v_(0), vused_(0), vsize_(0)
{ }
template <class T>
Field<T>::Field(size_t n, const T &val)
: v_(0), vused_(n), vsize_(0)
{
if(n > 0)
{
vsize_ = 1;
while(vsize_ < n)
vsize_ <<= 1;
v_ = new T[vsize_];
std::fill(v_, (v_ + vused_), val);
}
}
template <class T>
Field<T>::Field(const Field<T> &other)
: v_(new T[other.vsize_]), vsize_(other.vsize_), vused_(other.vused_)
{
std::copy(other.v_, (other.v_ + other.vused_), v_);
}
template <class T>
Field<T>& Field<T>::operator =(const Field<T> &other)
{
this->v_ = other.v_;
this->vused_ = other.vused_;
this->vsize_ = other.vsize_;
return *this;
}
FIELD MEMBERS
T *v_;
size_t vsize_;
size_t vused_;
Your copy constructor (of Field<>) seems OK, but the operator= is problematic.
Not only does it leak memory (what happens to the original v_?), but after that, two instances of Field<> hold a pointer to the same block of memory, and the one that is destructed first will invalidate the others v_ - and you can't even tell whether that has happened.
It's not always easy to decide how to deal with operator= - some think that implicit move semantics are okay, but the rest of us see how that played out with the majority of people, with std::auto_ptr. Probably the easiest solution is to disable copying altogether, and use explicit functions for moving ownership.
Your string handling in NumPair looks ok (strdup + free) and your Field container delete[] looks okay but it's hard to say because you don't show what v_ is.
eq mentions in a comment that you should also beware of how you are copying NumPairs. By default, C++ will give you an implicit member-wise copy constructor. This is where a RAII type like std::string makes your life easier: Your std::string containing struct can be copied without any special handling on your part and memory referenced in the string will be taken care of by the string's copy. If you duplicate your NumPair (by assigning it or returning it from a function for example) then the destruction of the temporary will free your strings out from under you.
Your copy constructor for Field just copies the pointers in v_. If you have two copies of a Field, all of the NumPairs in v_ will be deleted when the first Field goes out of scope, and then deleted again when the second one does.

optimize output value using a class and public member

Suppose you have a function, and you call it a lot of times, every time the function return a big object. I've optimized the problem using a functor that return void, and store the returning value in a public member:
#include <vector>
const int N = 100;
std::vector<double> fun(const std::vector<double> & v, const int n)
{
std::vector<double> output = v;
output[n] *= output[n];
return output;
}
class F
{
public:
F() : output(N) {};
std::vector<double> output;
void operator()(const std::vector<double> & v, const int n)
{
output = v;
output[n] *= n;
}
};
int main()
{
std::vector<double> start(N,10.);
std::vector<double> end(N);
double a;
// first solution
for (unsigned long int i = 0; i != 10000000; ++i)
a = fun(start, 2)[3];
// second solution
F f;
for (unsigned long int i = 0; i != 10000000; ++i)
{
f(start, 2);
a = f.output[3];
}
}
Yes, I can use inline or optimize in an other way this problem, but here I want to stress on this problem: with the functor I declare and construct the output variable output only one time, using the function I do that every time it is called. The second solution is two time faster than the first with g++ -O1 or g++ -O2. What do you think about it, is it an ugly optimization?
Edit:
to clarify my aim. I have to evaluate the function >10M times, but I need the output only few random times. It's important that the input is not changed, in fact I declared it as a const reference. In this example the input is always the same, but in real world the input change and it is function of the previous output of the function.
More common scenario is to create object with reserved large enough size outside the function and pass large object to the function by pointer or by reference. You could reuse this object on several calls to your function. Thus you could reduce continual memory allocation.
In both cases you are allocating new vector many many times.
What you should do is to pass both input and output objects to your class/function:
void fun(const std::vector<double> & in, const int n, std::vector<double> & out)
{
out[n] *= in[n];
}
this way you separate your logic from the algorithm. You'll have to create a new std::vector once and pass it to the function as many time as you want. Notice that there's unnecessary no copy/allocation made.
p.s. it's been awhile since I did c++. It may not compile right away.
It's not an ugly optimization. It's actually a fairly decent one.
I would, however, hide output and make an operator[] member to access its members. Why? Because you just might be able to perform a lazy evaluation optimization by moving all the math to that function, thus only doing that math when the client requests that value. Until the user asks for it, why do it if you don't need to?
Edit:
Just checked the standard. Behavior of the assignment operator is based on insert(). Notes for that function state that an allocation occurs if new size exceeds current capacity. Of course this does not seem to explicitly disallow an implementation from reallocating even if otherwise...I'm pretty sure you'll find none that do and I'm sure the standard says something about it somewhere else. Thus you've improved speed by removing allocation calls.
You should still hide the internal vector. You'll have more chance to change implementation if you use encapsulation. You could also return a reference (maybe const) to the vector from the function and retain the original syntax.
I played with this a bit, and came up with the code below. I keep thinking there's a better way to do this, but it's escaping me for now.
The key differences:
I'm allergic to public member variables, so I made output private, and put getters around it.
Having the operator return void isn't necessary for the optimization, so I have it return the value as a const reference so we can preserve return value semantics.
I took a stab at generalizing the approach into a templated base class, so you can then define derived classes for a particular return type, and not re-define the plumbing. This assumes the object you want to create takes a one-arg constructor, and the function you want to call takes in one additional argument. I think you'd have to define other templates if this varies.
Enjoy...
#include <vector>
template<typename T, typename ConstructArg, typename FuncArg>
class ReturnT
{
public:
ReturnT(ConstructArg arg): output(arg){}
virtual ~ReturnT() {}
const T& operator()(const T& in, FuncArg arg)
{
output = in;
this->doOp(arg);
return this->getOutput();
}
const T& getOutput() const {return output;}
protected:
T& getOutput() {return output;}
private:
virtual void doOp(FuncArg arg) = 0;
T output;
};
class F : public ReturnT<std::vector<double>, std::size_t, const int>
{
public:
F(std::size_t size) : ReturnT<std::vector<double>, std::size_t, const int>(size) {}
private:
virtual void doOp(const int n)
{
this->getOutput()[n] *= n;
}
};
int main()
{
const int N = 100;
std::vector<double> start(N,10.);
double a;
// second solution
F f(N);
for (unsigned long int i = 0; i != 10000000; ++i)
{
a = f(start, 2)[3];
}
}
It seems quite strange(I mean the need for optimization at all) - I think that a decent compiler should perform return value optimization in such cases. Maybe all you need is to enable it.