Pushing std::thread by value into a list - c++

My code looks like the following:
#include <list>
#include <thread>
void my_function(int val) {
// Empty function
}
int main() {
std::list<std::thread> threads;
for (int i = 0 ; i < 10 ; i++) {
threads.push_back(std::thread(my_function, i));
}
return 0;
}
The fact that I use threads.push_back() means that I run the copy-constructor std::thread::thread(const thread&).
Is it safe?
Should I use std::move ?
Please suppose that I don't know in advance how many threads I am going to need, so replacing the list by an array or by an std::vector, is not an option for me (std::vector would be an option only if I knew the number of threads in advance, as I cannot afford the vector's realloc operations).

The fact that I use threads.push_back() means that I run the copy-constructor
No, it does not. Since C++11 push_back is overloaded to accept an rvalue reference to the list's value type.
You cannot run std::thread's copy constructor, since it's declared as deleted. The above mentioned overload of push_back was added for this exact purpose of supporting move only types, like a thread handle.
If you want to initialize the thread directly into the container without a move, then emplace_back can do that. But you need to pass the parameters for the std::thread constructor in, not a thread that is initialized from them:
threads.emplace_back(my_function, i);

Related

Resize a std::vector<std::atomic_bool> assigning true to all atomic bools

I have a std::vector<std::atomic_bool> that I want to resize to some arbitrary n, wherein all newly created objects are assigned a value of true. The program will not build because resize() relies on the copy constructor of the data type, not its assignment operator. Is there any way to assign a default value to an atomic_bool or would I be stuck with using a loop and store()ing all the values?
What I've tried:
#include <atomic>
#include <vector>
class foo() {
public:
std::vector<std::atomic_bool> vec;
foo() {
std::atomic_bool temp(true);
vec.resize(100, std::atomic_bool(true)); //try 1
vec.resize(100, temp); //try 2
}
}
If T is neither copyable nor movable, then std::vector<T> cannot be resized. Period. In this case, you might want to consider std::deque.
std::deque<std::atomic_bool> D;
D.emplace_back(true); // write a helper to do this 100 times if you want
However, note that a standard library container of atomics is not atomic; adding new elements to the container is not an atomic operation so you will probably have to protect the container with a mutex, which might eliminate any benefits of storing atomics inside.
Brian's suggestion of a deque is sound and still allows O(1) random access, though I'd expect it to be a couple times slower than a vector. Kerrek's suggestion of a higher level class managing a vector's also workable.
FWIW, another option is wrapping the individual std::atomic_bools with a type that orchestrates copy construction as a combination of default construction and assignment:
struct Copy_Constructible_Atomic_Bool : std::atomic_bool
{
Copy_Constructible_Atomic_Bool(const std::atomic_bool& rhs)
{
std::atomic_bool::operator=(rhs);
}
Copy_Constructible_Atomic_Bool(const Copy_Constructible_Atomic_Bool& rhs)
{
std::atomic_bool::operator=(rhs);
}
};
Usage:
std::vector<Copy_Constructible_Atomic_Bool> vec;
std::atomic_bool temp;
temp = true;
vec.resize(100, temp);
atomics aren't designed to be moved, so you cant reallocate them to be somewhere else. However, you can replace them.
vec = std::vector<std::atomic_bool>(100, true);
(I'm not 100% certain you can use true here, but I believe you can.)

How to use vector (or different container) with non copyable class?

I have the following piece of code:
void f(){
.....
std::vector<PrepareLogFileThread> v;
for(int i = 0; i < list.length(); ++i){
PrepareLogFileThread a(
list[i],
LOG_TEMPLATE);
a.start();
v.push_back( a );
}
....
}
class PrepareLogFileThread inherits from a Thread class that uses pthread (we use c++98 standard.... and I can use auto_ptr).
The problem here is that Thread's copy constructor is private so that is doesn't mess up the execution or something (I am not the author of this class).
The idea here is that I create my PrepareLogFileThread objects, push_back to v, start them and then they all finish before f returns.
PrepareLogFileThread has in destructor call to pthread_join so that it finishes there.
But I can't because I copy a in line with push_back.
How can I do it without c++11 and changing Thread's copy constructor?
I am using gcc 4.4.6 and I can use auto_ptr.
Standard containers assume their elements support value semantics (which includes, in your parlance, being "copyable" - among other things).
One option is to create a container of your own that does not require such semantics. That is difficult, for various reasons.
Alternatively, have your container elements be something else which that does have value semantics, where the value uniquely identifies an instance of your PrepareLogFileThread class. An obvious choice for such a "something" is a pointer. For example;
void f()
{
std::vector<PrepareLogFileThread *> v;
for(int i = 0; i < list.length(); ++i){
PrepareLogFileThread *a = new PrepareLogFileThread(
list[i],
LOG_TEMPLATE);
a->start();
v.push_back( a );
}
}
Keep in mind, however, that it is necessary to delete the elements of the vector v before it ceases to exist - objects created with operator new are not automatically destroyed up when done. Failing to do this will result in a memory leak.
Note also that std::auto_ptr does not support value semantics, so should not be stored in a standard container.
You could store the pointer to the object.
std::vector<PrepareLogFileThread*> v;
You should be careful about the lifetime of the object.

initialing stl collection elements (not pointers) when no default constructor?

I have such private field:
private:
std::vector<OneItemIndex> oneItemIndexes;
My class declared this way, there are no default constructor:
public OneItemIndex(int instrumentId)
I want my field to contain 10 elements like this:
oneItemIndexes
0 OneItemIndex(0)
1 OneItemIndex(1)
...
10 OneItemIndex(10)
How can I do this? What should I write in constructor? Is it possible?
Or I have to use OneItemIndex* instead of OneItemIndex and call new OneItemIndex(instrumentId myself this way?
IndexesStorage::IndexesStorage(void)
{
for (int i = 0; i < 10; i++) {
oneItemIndexes.push_back(new OneItemIndex(i));
}
}
Note: actually I dont' have hardcoded 10 elements, i'm using dynamic Instrument::InstrumentsCount()
In C++11 and later, you can initialise container elements by passing constructor arguments to an emplace function:
oneItemIndexes.emplace_back(i);
Historically, you could copy-initialise them (as long as they're copyable; but that was a requirement for vector before C++11):
oneItemIndexes.push_back(OneItemIndex(i));
I don't understand the leap to dynamic allocation in the middle of your question. Why do you think you suddenly have to use dynamic allocation and store pointers?
Use your loop, but with normal, automatic-storage-duration objects. oneItemIndexes.push_back(OneItemIndex(i)) or even oneItemIndexes.emplace(i).
You could use std::generate. Sorry for brevity of my answer but I am on my phone.
If you really don't want to make your object default-constructible and copyable, the easiest way to solve this would be to use a vector of shared_ptrs to OneItemIndex. This way you get the copy/initialize semantics vector requires from shared_ptr, but you don't need to have them on OneItemIndex itself (a raw pointer would work too, but then you need to take care of deleting the elements somewhere).
Adding my code which works so far. I'm not sure how stable this code and how safe to use such hacks. To avoid calling copy-construct I have to call reserve
IndexesStorage::IndexesStorage(void)
{
oneItemIndexes.reserve(Instrument::InstrumentsCount());
for (int i = 0; i < Instrument::InstrumentsCount(); i++) {
oneItemIndexes.emplace_back(i);
}
}
OneItemIndex::OneItemIndex(OneItemIndex& rhs):
CustomIndex("blabla")
{
printf("OneItemIndex copy-construct must not be called, we make it public cause MSVC++ implementation!");
exit(0);
}

C++11 - emplace_back between 2 vectors doesn't work

I was trying to adapt some code and moving the content from a vector to another one using emplace_back()
#include <iostream>
#include <vector>
struct obj
{
std::string name;
obj():name("NO_NAME"){}
obj(const std::string& _name):name(_name){}
obj(obj&& tmp): name(std::move(tmp.name)) {}
obj& operator=(obj&& tmp) = default;
};
int main(int argc, char* argv[])
{
std::vector<obj> v;
for( int i = 0; i < 1000; ++i )
{
v.emplace_back(obj("Jon"));
}
std::vector<obj> p;
for( int i = 0; i < 1000; ++i )
{
p.emplace_back(v[i]);
}
return(0);
}
This code doesn't compile with g++-4.7, g++-4.6 and clang++: what it's wrong with it ?
I always got 1 main error about
call to implicitly-deleted copy constructor of obj
?
Although the existing answer provides a workaround using std::move that makes your program compile, it must be said that your use of emplace_back seems to be based on a misunderstanding.
The way you describe it ("I was trying to [...] moving the content from a vector to another one using emplace_back()") and the way you use it suggest that you think of emplace_back as a method to move elements into the vector, and of push_back as a method to copy elements into a vector. The code you use to fill the first instance of the vector seems to suggest this as well:
std::vector<obj> v;
for( int i = 0; i < 1000; ++i )
{
v.emplace_back(obj("Jon"));
}
But this is not what the difference between emplace_back and push_back is about.
Firstly, even push_back will move (not copy) the elements into the vector if only it is given an rvalue, and if the element type has a move assignment operator.
Secondly, the real use case of emplace_back is to construct elements in place, i.e. you use it when you want to put objects into a vector that do not exist yet. The arguments of emplace_back are the arguments to the constructor of the object. So your loop above should really look like this:
std::vector<obj> v;
for( int i = 0; i < 1000; ++i )
{
v.emplace_back("Jon"); // <-- just pass the string "Jon" , not obj("Jon")
}
The reason why your existing code works is that obj("Jon") is also a valid argument to the constructor (specifically, to the move constructor). But the main idea of emplace_back is that you need not create the object and then move it in. You don't benefit from that idea when you pass obj("Jon") instead of "Jon" to it.
On the other hand, in your second loop you are dealing with objects that were created before. There is no point in using emplace_back to move objects that exist already. And again, emplace_back applied to an existing object does not mean that the object is moved. It only means that it is created in-place, using the ordinary copy constructor (if that exists). If you want to move it, simply use push_back, applied to the result of std::move:
std::vector<obj> p;
for( int i = 0; i < 1000; ++i )
{
p.push_back(std::move(v[i])); // <-- Use push_back to move existing elements
}
Further notes
1) You can simplify the loop above using C++11 range-based for:
std::vector<obj> p;
for (auto &&obj : v)
p.push_back(std::move(obj));
2) Regardless of whether you use an ordinary for-loop or range-based for, you move the elements one by one, which means that the source vector v will remain as a vector of 1000 empty objects. If you actually want to clear the vector in the process (but still use move semantics to transport the elements to the new vector), you can use the move constructor of the vector itself:
std::vector<obj> p(std::move(v));
This reduces the second loop to just a single line, and it makes sure the source vector is cleared.
The problem is that
p.emplace_back(v[i]);
passes an lvalue to emplace_back, which means that your move constructor (which expects an rvalue reference) won't work.
If you actually want to move values from one container to another, you should explicitly call std::move:
p.emplace_back(std::move(v[i]));
(The idea behind a move constructor like obj(obj&& tmp) is that tmp should be an object that isn't going to be around for much longer. In your first loop, you pass a temporary object to emplace_back, which is fine -- a rvalue reference can bind to a temporary object and steal data from it because the temporary object is about to disappear. In your second loop, the object that you pass to emplace_back has a name: v[i]. That means it's not temporary, and could be referred to later in the program. That's why you have to use std::move to tell the compiler "yes, I really meant to steal data from this object, even though someone else might try to use it later.")
Edit: I'm assuming that your rather unusual usage of emplace_back is a relic of having to craft a little example for us. If that isn't the case, see #jogojapan's answer for a good discussion about why using a std::vector move constructor or repeated calls to push_back would make more sense for your example.

Why does my class's destructor get called when I add instances to a vector?

It seems that every time I add an object to the vector m_test, the destructor method is called. Am I missing something? How can I prevent this from happening?
class TEST
{
public:
TEST();
~TEST();
int * x;
};
TEST::TEST()
{
}
TEST::~TEST()
{
... it is called every time I push_back something to the vector ...
delete x;
}
vector<TEST> m_test;
for (unsigned int i=0; i<5; i++)
{
m_test.push_back(TEST());
}
The problem here is that you're violating the Rule of Three. Your class has a destructor so you need a copy-constructor and an assignment operator, too. Alternatively, you could not allow your class to be copied (for example by making T(T const&) and T& operator=(T const&) private, or by deriving from boost::noncopyable), and then resize the vector instead of using push_back.
In the first case, you can just push_back your class as you usually would. In the second, the syntax would be something like
std::vector<TEST> vec(5);
// vec now has five default-constructed elements of type TEST.
Not doing either of these things is a bad idea, as you are very likely to run into double deletion issues at some point -- even if you think you'll never copy or assign a TEST where x != nullptr, it's much safer to explicitly forbid it.
By the way, if you have member pointers that should be deleted when an object goes out of scope, consider using smart pointers like scoped_ptr, unique_ptr and shared_ptr (and maybe auto_ptr if you're unable to use Boost or C++11).
It's not called when you push_back, it's called when the temporary is destroyed.
To fix it in your example:
TEST test;
for (int i = 0; i < 5; ++i)
{
m_test.push_back(test);
}
Should only call it once.
Your code is creating a temporary TEST within the loop, using it in push_back, then that temporary is going out of scope when the loop ends/repeats and getting destroyed. That occurs exactly as it should, since the temporary TEST needs cleaned up.
If you want to avoid that, you need to do anything else but make a temporary object for each push. One potential solution is to:
vector<TEST> m_test(5); // Note reserving space in the vector for 5 objects
std::fill(m_test.begin(), m_test.end(), TEST()); // Fill the vector with the default ctor
Depending on how your STL is optimized, this may not need to make multiple copies.
You may also be able to get better handling if you implement a copy constructor in your TEST class, like:
TEST::TEST(const TEST & other)
{
x = new int(*other.x); // Not entirely safe, but the simplest copy ctor for this example.
}
Whether this is appropriate, or how you handle it, depends on your class and its needs, but you should typically have a copy constructor when you have defined your own regular constructor and destructor (otherwise the compiler will generate one, and in this case, it will result in copied and hanging pointers to x).
To avoid destruction of a temporary and to avoid copy constructors, consider using vector::resize or vector::emplace_back. Here's an example using emplace_back:
vector<TEST> m_test;
m_test.reserve(5);
for ( uint i=0; i<5; i++ )
{
m_test.emplace_back();
}
The vector element will be constructed in-place without the need to copy. When vt is destroyed, each vector element is automatically destroyed.
c++0x is required (use -std=c++0x with gnu). #include <vector> is of course also required.
If a default constructor is not used (for example, if the TEST::x was a reference instead of a pointer), simply add arguements to the call to emplace_back() as follows:
class TEST
{
public:
TEST( int & arg) : x(arg) {;} // no default constructor
int & x; // reference instead of a pointer.
};
. . .
int someInt;
vector<TEST> m_test;
m_test.reserve(5);
for ( uint i=0; i<5; i++ ) {
m_test.emplace_back( someInt ); // TEST constructor args added here.
}
The reserve() shown is optional but insures that sufficient space is available before beginning to construct vector elements.
vector.push_back() copies the given object into its storage area. The temporary object you're constructing in the push_back() call is destroyed immediately after being copied, and that's what you're seeing. Some compilers may be able to optimize this copy away, but yours apparently can't.
In m_test.push_back(TEST());, TEST() will create an temporary variable. After the vector copy it to its own memory, the temporary variable is destructed.
You may do like this:
vector<TEST> m_test(5, TEST());
The destructor is not only being called for the temporary variable.
The destructor will also get called when the capacity of the vector changes.
This happens often on very small vectors, less so on large vectors.
This causes:
A new allocation of memory (size based on a growth metric, not just size+1)
Copy of the old elements into the new allocation
Destruction of the elements in the old vector
Freeing of the old vector memory.
Copy construction of the new item onto the end of the new new vector.
See the third answer here:
Destructor is called when I push_back to the vector