Jump to content

Unable to pass function arguments to vector<thread>

I've created a vector<thread> t; and I've tried the following,

vector<thread> t;
for(int i=0;i<count;i++)
{
  t.push_back(MyFunc,i); // count is an Index variable passed to MyFunc()
}

.
.
.
  
void MyFunc(int Index)
{
  Array[Index] = Index; // Just an example...
}

but Qt Creator says "too many arguments" when I hover my mouse pointer over the above statement. Any idea why?

 

Thanks! :)

Nothing to see here ;)

Link to comment
https://linustechtips.com/topic/644767-unable-to-pass-function-arguments-to-vector/
Share on other sites

Link to post
Share on other sites

Push_back takes a tthread in this case.

Try to use emplace_back instead.

 

BTW: if you care about cross platform (I gues you do, otherwise you wouldnt use qt), use std::thread that is part of the C++ language.

Desktop: Intel i9-10850K (R9 3900X died 😢 )| MSI Z490 Tomahawk | RTX 2080 (borrowed from work) - MSI GTX 1080 | 64GB 3600MHz CL16 memory | Corsair H100i (NF-F12 fans) | Samsung 970 EVO 512GB | Intel 665p 2TB | Samsung 830 256GB| 3TB HDD | Corsair 450D | Corsair RM550x | MG279Q

Laptop: Surface Pro 7 (i5, 16GB RAM, 256GB SSD)

Console: PlayStation 4 Pro

Link to post
Share on other sites

push_back takes an already constructed object and copies it to the end of the array.

emplace_back constructs an object at the end of the array.

 

From that little bit of info you should be using emplace_back instead of push_back as you want to construct objects in the array not simply copy them to it.

vector<object> a;
object b;
a.push_back(b); // copy object to array.
a.push_back(object(blah, blah, blah)) // construct object then copy it to the array.
a.emplace_back(blah, blah, blah); // construct object at end of the array.

 

Also emplace_back usually yields better performance in many situations as well since you're avoiding an additional construction and copy operation.

CPU: Intel i7 - 5820k @ 4.5GHz, Cooler: Corsair H80i, Motherboard: MSI X99S Gaming 7, RAM: Corsair Vengeance LPX 32GB DDR4 2666MHz CL16,

GPU: ASUS GTX 980 Strix, Case: Corsair 900D, PSU: Corsair AX860i 860W, Keyboard: Logitech G19, Mouse: Corsair M95, Storage: Intel 730 Series 480GB SSD, WD 1.5TB Black

Display: BenQ XL2730Z 2560x1440 144Hz

Link to post
Share on other sites

As @trag1c mentions, push_back() causes an already existing object to be inserted at the end of the vector. emplace_back, on the other hand, takes the arguments you've passed it, and passes them to a constructor for what the vector holds (a thread in this case), then inserts it into the back. push_back involves constructing a thread, copying it to another thread, then putting it into the vector. emplace_back will construct a thread, then probably invokes std::move (I don't know the actual implementation) to make the vector own the object.

Link to post
Share on other sites

3 hours ago, trag1c said:

push_back takes an already constructed object and copies it to the end of the array.

moves into the array instead of copy in this case due to it being an rvalue&& and threads being uncopyable.

Quote

emplace_back will construct a thread, then probably invokes std::move (I don't know the actual implementation) to make the vector own the object.

emplace_back does a placement new straight into the vector, no moves or copies involved.

1474412270.2748842

Link to post
Share on other sites

23 minutes ago, fizzlesticks said:

moves into the array instead of copy in this case due to it being an rvalue&& and threads being uncopyable.

emplace_back does a placement new straight into the vector, no moves or copies involved.

Oh, right on, thanks for the info. Spot on for both points.

Link to post
Share on other sites

8 hours ago, fizzlesticks said:

moves into the array instead of copy in this case due to it being an rvalue&& and threads being uncopyable.

emplace_back does a placement new straight into the vector, no moves or copies involved.

Depends on how you call push_back.

I personally had problems with the following code:

auto list = eastl::vector();// EASTL but similar problem with STL
for (...)
{
	auto item = Item(xxx);
	item.DoSomething();
	list.push_back(item);
}

The problem here is that the destructor got called on the variable "item".

If the item class contains pointers, and the destructor free's those pointers, the copy of the item now has stale pointers.

So the move operator is not working because item is a lvalue?

 

Replacing the code by this works (although maybe a bit ugly):

auto list = eastl::vector();
for (...)
{
	list.emplace_back(xxx);
	auto item = &list.back();
	item.DoSomething();
}

 

Desktop: Intel i9-10850K (R9 3900X died 😢 )| MSI Z490 Tomahawk | RTX 2080 (borrowed from work) - MSI GTX 1080 | 64GB 3600MHz CL16 memory | Corsair H100i (NF-F12 fans) | Samsung 970 EVO 512GB | Intel 665p 2TB | Samsung 830 256GB| 3TB HDD | Corsair 450D | Corsair RM550x | MG279Q

Laptop: Surface Pro 7 (i5, 16GB RAM, 256GB SSD)

Console: PlayStation 4 Pro

Link to post
Share on other sites

7 hours ago, mathijs727 said:

The problem here is that the destructor got called on the variable "item".

If the item class contains pointers, and the destructor free's those pointers, the copy of the item now has stale pointers.

If that's the case, the copy constructor should either be making a deep copy or the class should be uncopyable. 

Quote

So the move operator is not working because item is a lvalue?

Correct. The move constructor is called when you have an rvalue&&. You can use the std::move(item) function which just casts something to an rvalue to move instead of copy (if your item class supports moving.)

 

Either way, your second snippet of code would be faster due to emplace_back avoiding a copy/move.

1474412270.2748842

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×