I have a class that resembles this:
However, after the initial constructor, the copy constructor is being called 10 times.
If I don't do the thread creation step. It gets called 4 times which is what I'd expect.
Why is that, and how do I avoid it?
Should I avoid using std::vector in this case and just do new delete instead?
#include <cstdio>
#include <vector>
class A
{
public:
A() { printf("hello\n"); }
~A() { printf("Goodbye\n"); }
A(const A&)
{
printf("copy constructing\n");
}
Thread() { }
};
int main()
{
std::vector<A> a(4, A);
for (int i = 0; i < a.size(); i++){
threads_.create_thread(boost::bind(&A::Thread, a[i]));
}
}
Ok, I found the problem.
This:
threads_.create_thread(boost::bind(&A::Thread, a[i]));
Should be:
threads_.create_thread(boost::bind(&A::Thread, &a[i]));
Take a look at Boost.Ref
for (int i = 0; i < a.size(); i++){
threads_.create_thread(boost::bind(&A::Thread, boost::ref(a[i]) ));
}
this is from the Boost.Bind :
The arguments that bind takes are
copied and held internally by the
returned function object. For example,
in the following code:
int i = 5;
bind(f, i, _1);
a copy of the value of i is stored
into the function object. boost::ref
and boost::cref can be used to make
the function object store a reference
to an object, rather than a copy:
int i = 5;
bind(f, ref(i), _1);
bind(f, cref(42), _1);
Threads are irrelevant here. The "problem" is with boost::bind; it makes copies of the arguments you give it, so it can use the value later when invoked. Use ref so have it store a reference instead.
Should I avoid using std::vector in this case and just do new delete instead?
Huh? Why would you do that? You need to get over the fact copies are made; that just happens. You should be worried about writing clean, maintainable code first, not whether or not you happen to make a copy. There's no reason to use new[] over a std::vector; never use delete.
Related
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);
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
I need to initialize an array of objects of a parametrized constructor . How can i do it in best possible way ?
# include<iostream>
# include<conio.h>
# include<stdio.h>
using namespace std;
class A
{
public:
int a;
A();
A(int x)
{
a=x;
}
};
int main()
{
A *a1,a2(1);
a1 = (A*)malloc(sizeof(A)*10); // equivalent to A[10].
for(int i=0;i<10;i++) a1[i]=a2; // Initialization is important in any program.
for(int i=0;i<10;i++) cout<<a1[i].a;
getch();
return 0;
}
This does work but is there some other way better than this ?
The C++ way would be to use a std::vector.
std::vector<A> a1(10, 1);
creates 10 A's initialized by 1.
This is solved using std::vector constructor taking size and base element :
A a2(1);
std::vector<A> tab(10, a2);
Note that malloc does not construct objects, and so calling a1[i]=a2 is bad form. It probably seems to work fine since they are POD-ish objects, but this is not the proper way to do C++. It is undefined behavior, which is completely unpredictable. It may work ten thousand times in a row, and then erase your bank account. You should use new instead, which also constructs. Or better yet, use a vector, like the other answers suggest. Also, be sure that the default constructor initializes the data, and initialization will be less of a worry.
If you really must use malloc, the "correct way" to initialize is this:
std::uninitialized_copy(a1, a1+10, a2); //constructs and assigns
which is roughly equivalent to:
{
int i=0;
try {
for(i=0; i<10; ++i)
new(a1+i)A(a2); //constructs and initializes in the buffer
} catch(...) {
try {
for(; i>=0; --i)
(a1+i)->~A(); //destroy if an error occured
} catch(...) {
std::terminate();
}
throw;
}
}
With the code below, the question is:
If you use the "returnIntVector()" function, is the vector copied from the local to the "outer" (global) scope? In other words is it a more time and memory consuming variation compared to the "getIntVector()"-function? (However providing the same functionality.)
#include <iostream>
#include <vector>
using namespace std;
vector<int> returnIntVector()
{
vector<int> vecInts(10);
for(unsigned int ui = 0; ui < vecInts.size(); ui++)
vecInts[ui] = ui;
return vecInts;
}
void getIntVector(vector<int> &vecInts)
{
for(unsigned int ui = 0; ui < vecInts.size(); ui++)
vecInts[ui] = ui;
}
int main()
{
vector<int> vecInts = returnIntVector();
for(unsigned int ui = 0; ui < vecInts.size(); ui++)
cout << vecInts[ui] << endl;
cout << endl;
vector<int> vecInts2(10);
getIntVector(vecInts2);
for(unsigned int ui = 0; ui < vecInts2.size(); ui++)
cout << vecInts2[ui] << endl;
return 0;
}
In theory, yes it's copied. In reality, no, most modern compilers take advantage of return value optimization.
So you can write code that acts semantically correct. If you want a function that modifies or inspects a value, you take it in by reference. Your code does not do that, it creates a new value not dependent upon anything else, so return by value.
Use the first form: the one which returns vector. And a good compiler will most likely optimize it. The optimization is popularly known as Return value optimization, or RVO in short.
Others have already pointed out that with a decent (not great, merely decent) compiler, the two will normally end up producing identical code, so the two give equivalent performance.
I think it's worth mentioning one or two other points though. First, returning the object does officially copy the object; even if the compiler optimizes the code so that copy never takes place, it still won't (or at least shouldn't) work if the copy ctor for that class isn't accessible. std::vector certainly supports copying, but it's entirely possible to create a class that you'd be able to modify like in getIntVector, but not return like in returnIntVector.
Second, and substantially more importantly, I'd generally advise against using either of these. Instead of passing or returning a (reference to) a vector, you should normally work with an iterator (or two). In this case, you have a couple of perfectly reasonable choices -- you could use either a special iterator, or create a small algorithm. The iterator version would look something like this:
#ifndef GEN_SEQ_INCLUDED_
#define GEN_SEQ_INCLUDED_
#include <iterator>
template <class T>
class sequence : public std::iterator<std::forward_iterator_tag, T>
{
T val;
public:
sequence(T init) : val(init) {}
T operator *() { return val; }
sequence &operator++() { ++val; return *this; }
bool operator!=(sequence const &other) { return val != other.val; }
};
template <class T>
sequence<T> gen_seq(T const &val) {
return sequence<T>(val);
}
#endif
You'd use this something like this:
#include "gen_seq"
std::vector<int> vecInts(gen_seq(0), gen_seq(10));
Although it's open to argument that this (sort of) abuses the concept of iterators a bit, I still find it preferable on practical grounds -- it lets you create an initialized vector instead of creating an empty vector and then filling it later.
The algorithm alternative would look something like this:
template <class T, class OutIt>
class fill_seq_n(OutIt result, T num, T start = 0) {
for (T i = start; i != num-start; ++i) {
*result = i;
++result;
}
}
...and you'd use it something like this:
std::vector<int> vecInts;
fill_seq_n(std::back_inserter(vecInts), 10);
You can also use a function object with std::generate_n, but at least IMO, this generally ends up more trouble than it's worth.
As long as we're talking about things like that, I'd also replace this:
for(unsigned int ui = 0; ui < vecInts2.size(); ui++)
cout << vecInts2[ui] << endl;
...with something like this:
std::copy(vecInts2.begin(), vecInts2.end(),
std::ostream_iterator<int>(std::cout, "\n"));
In C++03 days, getIntVector() is recommended for most cases. In case of returnIntVector(), it might create some unncessary temporaries.
But by using return value optimization and swaptimization, most of them can be avoided. In era of C++11, the latter can be meaningful due to the move semantics.
In theory, the returnIntVector function returns the vector by value, so a copy will be made and it will be more time-consuming than the function which just populates an existing vector. More memory will also be used to store the copy, but only temporarily; since vecInts is locally scoped it will be stack-allocated and will be freed as soon as the returnIntVector returns. However, as others have pointed out, a modern compiler will optimize away these inefficiencies.
returnIntVector is more time consuming because it returns a copy of the vector, unless the vector implementation is realized with a single pointer in which case the performance is the same.
in general you should not rely on the implementation and use getIntVector instead.
I am trying to create an array of class objects taking an integer argument. I cannot see what is wrong with this simple little code. Could someone help?
#include <fstream>
#include <iostream>
using namespace std;
typedef class Object
{
int var;
public:
Object(const int& varin) : var(varin) {}
} Object;
int main (int argc, char * const argv[])
{
for(int i = 0; i < 10; i++)
{
Object o(i)[100];
}
return 0;
}
In C++ you don't need typedefs for classes and structs. So:
class Object
{
int var;
public:
Object(const int& varin) : var(varin) {}
};
Also, descriptive names are always preferrable, Object is much abused.
int main (int argc, char * const argv[])
{
int var = 1;
Object obj_array[10]; // would work if Object has a trivial ctor
return 0;
}
Otherwise, in your case:
int main (int argc, char * const argv[])
{
int var = 1;
Object init(var);
Object obj_array[10] = { var, ..., var }; // initialize manually
return 0;
}
Though, really you should look for vector
#include <vector>
int main (int argc, char * const argv[])
{
int var = 1;
vector<Object> obj_vector(10, var); // initialize 10 objects with var value
return 0;
}
dirkgently's rundown is fairly accurate representation of arrays of items in C++, but where he is initializing all the items in the array with the same value it looks like you are trying to initialize each with a distinct value.
To answer your question, creating an array of objects that take an int constructor parameter. You can't, objects are created when the array is allocated and in the absence of a trivial constructor your compiler will complain. You can however initialize an array of pointers to your object but you really get a lot more flexibility with a vector so my following examples will use std::vector.
You will need to initialize each of the object separately if you want each Object to have a distinct value, you can do this one of two ways; on the stack, or on the heap. Lets look at on-the-stack first.
Any constructor that take a single argument and is not marked as explicit can be used as an implicit constructor. This means that any place where an object of that type is expected you can instead use an instance of the single parameter type. In this example we create a vector of your Object class and add 100 Objects to it (push_back adds items to a vector), we pass an integer into push_back which implicitly creates an Object passing in the integer.
#include <vector>
int main() {
std::vector<Object> v;
for(int i = 0; i < 100; i++) {
v.push_back(i);
}
}
Or to be explicit about it:
#include <vector>
int main() {
std::vector<Object> v;
for(int i = 0; i < 100; i++) {
v.push_back(Object(i));
}
}
In these examples, all of the Object objects are allocated on the stack in the scope of the for loop, so a copy happens when the object is pushed into the vector. Copying a large number of objects can cause some performance issues especially if your object is expensive to copy.
One way to get around this performance issue is to allocate the objects on the heap and store pointers to the objects in your vector:
#include <vector>
int main() {
std::vector<Object*> v;
for(int i = 0; i < 100; i++) {
v.push_back(new Object(i));
}
for(int i = 0; i < 100; i++) {
delete v[i];
}
}
Since our objects were created on the heap we need to make sure that we delete them to call their deconstructor and, free their memory, this code does that in the second loop.
Manually calling delete has it's own caveats, if you pass these pointers to other code you can quickly loose track of who owns the pointers and who should delete them. An easier way to solve this problem is to use a smart pointer to track the lifetime of the pointer, see either boost::shared_ptr or tr1::shared_ptr which are reference-counted pointers :
#include <vector>
int main() {
std::vector<shared_ptr<Object> > v;
for(int i = 0; i < 100; i++) {
Object* o = new Object(i);
v.push_back(shared_ptr<Object>(o));
}
}
You'll notice that the shared_ptr constructor is explicit, this is done intentionally to make sure that the developer is intentionally stuffing their pointer into the shared pointer. When all references to an object are released the object will automatically be deleted by the shared_ptr, freeing us of the need to worry about it's lifetime.
If you want to stick to arrays, then you must either initialize manually or use the default constructor. However, you can get some control by creating a constructor with a default argument. This will be treated as a default constructor by the compiler. For example, the following code prints out the numbers 0, ..., 9 in order. (However, I'm not sure that the standard dictates that the objects in the array must be constructed in order. It might be implementation dependent, in which case the numbers may appear in arbitrary order.)
#include <iostream>
using namespace std;
struct A {
int _val;
A(int val = initializer()) : _val(val) {}
static int initializer() { static int v = 0; return v++; }
};
int main()
{
A a[10];
for(int i = 0; i < 10; i++)
cout << a[i]._val << endl;
}