I know that std::queue uses a std::deque by default as its internal container. I could not find the same info for TBB.
I have a legacy multithreaded application that currently uses a thread-safe wrapper around a std::queue<void*, std::list<void*>> to store relatively large objects (58 bytes). I am currently looking for better alternatives to improve performance.
One option is to get rid of the linked list and use the default std::deque as the internal container and switch from pointer-to-object to storing objects by value. std::deque being allocated in chunks would scale better memory-wise as no. of elements increase. Also having a few elements contiguous would be helpful from a cache perspective.
The other option is to use TBB's concurrent_bounded_queue. But I don't have enough information about that to know whether storing my object as value would be a feasible option.
Any alternative suggestions are also welcome.
You can store objects as value in tbb::concurrent_bounded_queue.
You can refer to the below example code for implementation.
#include <tbb/concurrent_queue.h>
#include <tbb/concurrent_priority_queue.h>
#include <iostream>
static int value=0;
static int obj_count=0; // count of objects
class Myclass{
public:
int myarray[10];
Myclass()
{
for(int i=0;i<10;i++){
myarray[i]=value++; //initializing the values of myarray for each new object
}
}
void show()
{
std::cout<< " Values of object "<< (++obj_count ) <<" are: ";
for(int i=0;i<10;i++){
std::cout<<myarray[i]<<" "; // printing the data values of myarray object
}
std::cout<<std::endl;
}
};
int main()
{
Myclass m[10];
tbb::concurrent_bounded_queue<Myclass> queue; // creatiing a concurrent_bounded_queue of type "Myclass"
for(int i=0;i<10;++i){
queue.try_push(m[i]); //pushing each Myclass object into the concurrent_bounded_queue
}
for(int i=0;i<10;i++){
Myclass val;
if(queue.try_pop(val)) //pops it from the queue, assigns it to destination, and destroys the original value.
{
val.show(); //To print/access the data of myarray for each popped Myclass object.
}
}
std::cout<< std::endl;
return 0;
}
Compilation and execution can be done as shown in the screenshot link attached here-->.
compilation and execution
I hope this might help you.
Thanks,
Santosh
Related
I am trying to make a class with decendants of the same class, to make a tree, but when i try to access something insode of the vector it never works. i get an exception: std::length_error when trying to access the string.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class A {
public:
string name;
vector<A*> children;
};
int main()
{
A cl;
cl.name= "HI!";
for(int i = 0; i < 10;i++) {
A newCl;
newCl.name= "World!";
cl.children.push_back(&newCl);
}
for(int i = 0; i < 10;i++) {
// error here:
cout << cl.children[i]->name << endl;
}
return 0;
}
Anybody know an easier way to make a tree in C++, or how to fix this?
The problem is in this loop
for(int i = 0; i < 10;i++) {
A newCl;
newCl.name= "World!";
cl.children.push_back(&newCl);
}
The variable newCl will cease to exist at the end of the iteration and you are inserting its address in the vector. When you access it, you are accessing a dangling pointer, this is undefined behavior and your program can crash, produce garbage or anything in between.
You can use heap allocation as proposed by Oblivion, but in such a case you might want to consider the use of smart pointers for memory management.
Otherwise, you can have a vector of values std::vector<A> instead of pointers, possible from C++17 (for more details, see: How can I declare a member vector of the same class?)
Edit: I clarified the use of std::vector<A> after Chipster's comment.
You store reference to a temporary as children:
A newCl;
newCl.name= "World!";
cl.children.push_back(&newCl);
Once you are out of scope the children will dangle.
A* newCl = new A;
Should fix. But you have to go through the vector to free your children.
If you had a reason to use pointers, it is better to use smart pointers:
vector<shared_ptr<A>> children;
Live
I am having a situation where I have to call a function in loop with pointer (to a class object) as a parameter. Issue is, I cannot modify the signature of that function and that with every iteration of loop, I have to initialize the pointer. This will lead to memory leak as I cannot delete the pointer (after passing it to the function) inside the loop. Is there any way I can prevent memory leak in such a case?
I would like to explain with a simple example:
class testDelete
{
public:
void setValue(int* val) {vec.push_back(val);};
void getValue();
private:
vector <int*> vec;
};
void testDelete::getValue()
{
for (int i=0;i<vec.size();i++)
{
cout << "vec[" << i << "] = " << *vec[i]<<"\n";
}
}
int main()
{
testDelete tD;
int* value = NULL;
for (int i=0;i<10;i++)
{
value=new int(i+1);
/*I am not allowed to change this function's signature, and hence I am forced to pass pointer to it*/
tD.setValue(value);
/*I cannot do delete here otherwise the getValue function will show garbage value*/
//delete value;
}
tD.getValue();
return 0;
}
If deleteTest wants to use pointers of maybe gone objects it should hold std::weak_ptrs.
Holding on to a raw pointer and dereferencing it later is dangerous (unless you can make sure the object is still alive, a.k.a don't use raw but smart pointers).
[...] I cannot modify the signature of that function and that with every
iteration of loop, I have to initialize the pointer. Is there any way I can prevent memory leak in such a case?
If you need dynamically allocated objects, use smart pointers (eg std::smart_ptr for shared ownership). If you do not need to dynamically allocate them then don't.
For the sake of the example lets assume you cannot modify deleteTest, then for integers there is no reason to dynamically allocate anything
int main()
{
std::array<int,10> x;
testDelete tD;
for (int i=0;i<10;i++)
{
x[i] = i+1;
tD.setValue(&x[i]);
}
tD.getValue();
return 0;
}
Take this code with a grain of salt, it is actually deleteTest that needs to be fixed to avoid creating trouble.
TL;DR
In your example you have actually two problems. deleteTest may try to access already gone objects and memory leaks in main. Using smart pointers solves both.
Store the integers in a container:
int main()
{
std::vector<int> values(10);
testDelete tD;
for (int i=0;i<10;i++)
{
values[i] = i + 1;
tD.setValue(&values[i]);
}
tD.getValue();
return 0;
}
I'm trying to make this code work, but the object keep getting destroyed...
I've found that it has to do with the object being copied to the vector, but can't find any way to prevent it...
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Obje
{
private:
static int instances;
int id;
public:
static int getInstances();
void getId();
virtual void myClass();
Obje(int auxId);
~Obje();
};
int Obje::instances = 0;
int Obje::getInstances()
{
return instances;
}
Obje::Obje(int auxId)
{
this->id = auxId;
cout << "Obje Created." << endl;
Obje::instances++;
}
Obje::~Obje()
{
cout << "Obje Destroyed." << endl;
Obje::instances--;
}
void Obje::myClass()
{
cout << "Obje." << endl;
}
void Obje::getId()
{
cout << this->id << endl;
}
int main()
{
vector <Obje> list;
Obje *a = new Obje(59565);
list.push_back(*a);
Obje *b = new Obje(15485);
list.push_back(*b);
for(vector<Obje>::iterator it = list.begin(); it != list.end(); ++it)
{
it->getId();
}
return 0;
}
It Generates this output:
Obje Created.
Obje Created.
Obje Destroyed.
59565
15485
Obje Destroyed.
Obje Destroyed.
What does it mean the T(const T& new); i've saw as fix for this?
First of all, it is a bad practice to allocate an object in heap without using smart pointers and forgetting to delete it. Especially, when you are creating it just to make a copy of it.
list.push_back(*a); creates a copy of *a in vector. To create an item in vector without copying another item, you can do list.emplace_back(/*constructor parameters*/);, which is available from c++11. (see http://en.cppreference.com/w/cpp/container/vector/emplace_back)
So, to make the result behavior match your expectations, you should go
vector <Obje> vec;
vec.emplace_back(59565);
vec.emplace_back(15485);
for(const auto & item : vec)
{
item.getId();
}
By the way, it is also a quite bad practice to call a vector as a list, as a list is a different container type and reading such code may be confusing a bit. I guess, I am starting being annoying, but it is better to call method getId as showId as now it returns nothing.
Regarding the use of heap, new and pointer, see my comment in your question.
Regarding the issue object was destroyed, the vector maintains an internal buffer to store object. When you push_back new object to the vector, if its internal buffer is full, it will (the stuff which will be executed when exception occurs won't be mentioned here.):
allocate new internal buffer which is big enough to store its new data.
move data from old internal buffer to new internal buffer.
destroy old buffer.
Hence, your object will be destroyed and copied to new location in this case, hence copy constructor will make it clearer to you.
P/S: AFAIK, some compilers move its data by memmove or std::move
In my C++ code I have a class Object equipped with an id field of type int. Now I want to create a vector of pointers of type Object*. First I tried
vector<Object*> v;
for(int id=0; id<n; id++) {
Object ob = Object(id);
v.push_back(&ob);
}
but this failed because here the same address just repeats itself n times. If I used the new operator I would get what I want but I'd like to avoid dynamic memory allocation. Then I thought that what I need is somehow to declare n different pointers before the for loop. Straightforward way to this is to declare an array so I did this :
vector<Object*> v;
Object ar[n];
for(int i=0; i<n; i++) {
ar[i] = Object(i);
}
for(int i=0; i<n; i++) {
v.push_back(ar+i);
}
Is there still possibility to get a memory leak if I do it this way? Also going through an array declaration is a bit clumsy in my opinion. Are there any other ways to create vector of pointers but avoid manual memory management?
EDIT: Why do I want pointers instead of just plain objects?
Well I modified the original actual situation a bit because I thought in this way I can represent the question in the simplest possible form. Anyway I still think the question can be answered without knowing why I want a vector of pointers.
Actually I have
Class A {
protected:
vector<Superobject*> vec;
...
};
Class B: public A {...};
Class Superobject {
protected:
int id;
...
}
Class Object: public Superobject {...}
In derived class B I want to fill the member field vec with objects of type Object. If the superclass didn't use pointers I would have problems with object slicing. So in class B constructor I want to initialize vec as vector of pointers of type Object*.
EDIT2
Yes, it seems to me that dynamic allocation is the reasonable option and the idea to use an array is a bad idea. When the array goes out of scope, things will go wrong because the pointers in vector point to memory locations that don't necessarily contain the objects anymore.
In constructor for class B I had
B(int n) {
vector<Object*> vec;
Object ar[n];
for(int id=0; id<n; id++) {
ar[id] = Object(id);
}
for(int id=0; id<n; id++) {
v.push_back(ar+id);
}
}
This caused very strange behavior in objects of class B.
In this loop:
for(int id=0; id<n; id++) {
Object ob = Object(id);
v.push_back(&ob);
}
You are creating n times Object instance on stack. At every iteration there is created and removed element. You can simply avoid this using that:
for(int id=0; id<n; id++) {
Object* ob = new Object(id);
v.push_back(ob);
}
thanks that every new element exist on heap not on the stack. Try to add to in class Object constructor something like that:
std::cout<<"Object ctor()\n";
and the same in the destructor:
std::cout<<"Object dtor()\n";
If you dont want to create these objects with "new" try reason written by #woolstar
Your question about memory leaks makes me think you are worried about the lifecycle and cleanup of these objects. I originally proposed shared_ptr wrappers, but C++11 gave us unique_ptr, and C++14 filled in the missing make_unique. So with all that we can do:
vector<unique_ptr<SuperObject>> v ;
Which you create in place with the wonderfulness of perfect forwarding and variadic templates,
v.push_back( make_unique<Object>( ... ) ) ;
Yes you are going to have to live with some heap allocations, but everything will be cleaned up when v goes away.
Someone proposed a boost library, ptr_container, but that requires not only adding boost to your project, but educating all future readers what this ptr_container is and does.
No there is no memory leak in your version. When the program leaves your scope the vector as well the array are destroyed. To your second question: Why not simply store the objects directly in an vector?
vector<Object> v;
for(int i = 0; i < n; i++)
{
Object obj = Object(i);
v.push_back(obj);
}
Is it safe to return a vector that's been filled with local variables?
For example, if I have...
#include <vector>
struct Target
{
public:
int Var1;
// ... snip ...
int Var20;
};
class Test
{
public:
std::vector<Target> *Run(void)
{
std::vector<Target> *targets = new std::vector<Target>;
for(int i=0; i<5; i++) {
Target t = Target();
t.Var1 = i;
// ... snip ...
t.Var20 = i*2; // Or some other number.
targets->push_back(t);
}
return targets;
}
};
int main()
{
Test t = Test();
std::vector<Target> *container = t.Run();
// Do stuff with `container`
}
In this example, I'm creating multiple Target instances in a for loop, pushing them to the vector, and returning a pointer to it. Because the Target instances were allocated locally, to the stack, does that mean that the returned vector is unsafe because it's referring to objects on the stack (that may soon be overwritten, etc)? If so, what's the recommended way to return a vector?
I'm writing this in C++, by the way.
Elements get copied when you push_back them into a vector (or assign to elements). Your code is therefore safe – the elements in the vector are no references to local variables, they are owned by the vector.
Furthermore, you don’t even need to return a pointer (and never handle raw pointers, use smart pointers instead). Just return a copy instead; the compiler is smart enough to optimise this so that no actual redundant copy is made.