I am trying to do something similar to the last code in this
In the code however you see that
vec_thr.emplace_back(&Test::testme, std::move(t1), std::cref(str)); is called inside the main function.
I would like to do that from a member function of the object Test.
So I did
#include <thread>
#include <string>
#include <vector>
#include <iostream>
class Test
{
private:
public:
void testme(const std::string& _str)
{
std::cout << "Hello " + _str << std::endl;
}
void testFurther(const std::string& _str){
std::vector<std::thread> vec_thr;
// pass the constructor parameters you would have passed to std::thread
// to the emplace_back() function - they are forwarded to the thread that
// is constructed "in place" inside the vector
for(int i=0;i<2;i++){
//HERE I am trying how to write this correctly trying the following:
// vec_thr.emplace_back(&Test::testme, std::move(t1), std::cref(str));
vec_thr.emplace_back(testme, std::move(this), std::cref(_str));
// vec_thr.emplace_back(testme, std::cref(_str));
}
// Don't forget to join all your threads to make sure
// they complete before moving on/exiting
for(auto& t: vec_thr)
t.join();
}
};
int main()
{
const std::string str = "there";
Test t1/*, t2*/;
t1.testFurther(str);
}
However it is not working. I got the error message
error: invalid use of non-static member function
Is there a way to be able to do this.
I want to do the exact same thing that was done originally from the main function
It seems I have solve the problem by changing the class Test function testFurther to
void testFurther(const std::string& _str){
std::vector<std::thread> vec_thr;
// pass the constructor parameters you would have passed to std::thread
// to the emplace_back() function - they are forwarded to the thread that
// is constructed "in place" inside the vector
for(int i=0;i<2;i++){
// vec_thr.emplace_back(&Test::testme, std::move(t1), std::cref(str));
// vec_thr.emplace_back(testme, std::move(this), std::cref(_str));
// vec_thr.emplace_back(&testme, this, std::cref(_str)); // ISO forbid taking the address of an unqualified or parenthesized non-static member function
vec_thr.emplace_back(&Test::testme, this, std::cref(_str)); //THIS WORKS
// vec_thr.emplace_back(testme, std::cref(_str));
}
// Don't forget to join all your threads to make sure
// they complete before moving on/exiting
for(auto& t: vec_thr)
t.join();
}
with this it seems to be working well.
I just wonder why I have to use &Test::testme since Test is the name of the class not of an object instance
Related
Could you please help to review the below code? is there any issue if a local std::function is out of its "life"? Thanks in advance.
class Test {
public:
void commit(std::function<void()> func)
{
// return immediately
dispatch_async(conqueue, ^{
// in order to call func when it is out of "life"
sleep(5);
func(); // is there any issue? the func should be invalid at this moment?
});
}
void test() {
std::string name = "test";
std::function<void()> func = [name, this] () {
printf("%lx %s\n", &name, name.c_str());
std::cout << "callback"<<std::endl;
};
// async
commit(func);
}
//...
};
OK, I ran some tests and have changed my view on this. The code is safe because func is captured by value (i.e. the block inherits a copy).
I proved this to myself with the following test program (you will need MacOS to run this):
// clang block_test.mm -lc++
#include <iostream>
#include <unistd.h>
#include <dispatch/dispatch.h>
struct Captured
{
Captured () {}
Captured (const Captured &c) { std::cout << "Copy constructor\n"; }
void Foo () const { std::cout << "Foo\n"; }
};
int main ()
{
Captured c;
// return immediately
dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
sleep(5);
c.Foo ();
});
sleep (10);
};
Output:
Copy constructor
Copy constructor
Foo
I'm not sure why the copy constructor is called twice though. Ask Apple.
Update: There's a good writeup on working with blocks here. That's what that funny 'hat' syntax is.
It's safe. Apple "Blocks" capture non-__block variables by value, so the block contains a copy of the std::function inside it, so the lifetime of the block's copy of the variable is the same as the block itself.
(P.S. Even if the variable was declared __block, it would still be safe. Blocks capture __block variables kind of "by reference", in that multiple blocks, as well as the original function scope, share the state of the variable. However, the underlying mechanism of __block ensures that the variable is moved to the heap if it is used by a block that outlives the function's scope. So for a __block variable, its lifetime lasts until all blocks that captured it have been destroyed.)
I was looking to an exercise I did, specifically a class "threads manager" which manage threads (omg really? lol) by storing them inside an array of "typedef void *HANDLE;" declared inside a struct GROUP.
So I already made it working, but I saw that I was converting the "HANDLE", so "void*", by "reinterpret_cast" conversion to "std::thread*".
After I saw that I worried: how and can I convert it directly to an std::thread object?
I did this code for example:
#include <iostream>
#include <thread>
typedef void *HANDLE;
class thread_obj {
public:
void operator()(int x){
for(int i = 0x0; i < x; i++){
std::cout << "i = " << i << std::endl;
}
}
};
int main(){
std::thread thr(thread_obj(), 0x3);
HANDLE test = &thr;
std::thread *p_thr = reinterpret_cast<std::thread*>(test);
p_thr->join();
return 0x0;
}
This is the original code.
If instead I do:
std::thread p_thr = reinterpret_cast<std::thread&>(test);
or:
std::thread p_thr = *reinterpret_cast<std::thread*>(test);
or:
std::thread *temp = reinterpret_cast<std::thread*>(test);
std::thread p_thr = *temp;
I always get:
error: use of deleted function ‘std::thread::thread(std::thread&)’
On "reinterpret_cast" line for the first and second case, and on the following assignment line for the third.
Now I suppose the problem is with the copy constructor called.
I searched a little and I opened the thread class and I found it:
thread(thread&) = delete;
So :/ searching a little I only found the solution on which you override the copy constructor.
In this case I think a solution could be make a superclass an re-declare this deleted constructor, right? But this is just a waste of time :/
So is there a way to convert this "void*" to "std::thread" object, again to a "std::thread" object?
If yes or no can you explain me in detail please?
Thank you so much
have a nice day and coding :D
What you really need is
std::thread& ref_thr = *reinterpret_cast<std::thread*>(test);
// ^ declare a reference to a std::thread
and then you can use ref_thr just like you would use a normal object.
As you've found, the copy constructor for std::thread is deleted, so if you actually want to create a thread object from test, then you need to move the casted object into new_thr like
std::thread new_thr = std::move(*reinterpret_cast<std::thread*>(test));
but this means that the object pointer to by test is no longer usable as it was moved into new_thr. This is why you want to use a reference, unless you actually want to move it.
I have the following code:
#include <iostream>
#include <memory>
#include <vector>
class Test
{
public:
Test() {}
~Test() { std::cerr << "Delete\n"; }
};
std::vector<std::shared_ptr<Test>> makeList()
{
std::vector<std::shared_ptr<Test>> list;
list.push_back(std::make_shared<Test>(Test()));
return std::move(list);
}
int main(int argc ,char **argv)
{
std::vector<std::shared_ptr<Test>> list;
std::cerr << "Before\n";
list = makeList();
std::cerr << "After\n";
return 0;
}
Which I compile with:
clang++ -std=c++14 -o ptr ptr.cpp
The output is:
Before
Delete
After
Delete
My question is: why is there an object being deleted in the makeList function? My assumption was that the list from the function would be moved into list from main and that therefore no object would be deleted/recreated in the process?
Can this be avoided (as obviously this code is not optimum)?
2 Changes:
std::vector<std::shared_ptr<Test>> makeList()
{
std::vector<std::shared_ptr<Test>> list;
// make_shared does not need a copy of an object, just constructor arguments
list.push_back(std::make_shared<Test>());
// return std::move(list) will defeat RVO. Never do that.
return list;
}
So, the important part is :
list.push_back(std::make_shared<Test>(Test()));
->
list.push_back(std::make_shared<Test>());
Just for clarification because I had the same today, and I had trouble seeing the difference.
list.push_back(std::make_shared<Test>(Test()));
Here temporary is created with Test(). Then copy c-tor for Test is invoked and temporary is destroyed. It is the first destructor call.
The second destructor call appears in the end of the program when list is destroyed.
The right form to avoid temporary creation is:
list.push_back(std::make_shared<Test>());
Besides you shouldn't use std::move returning the value because compiler cannot apply Return value optimisation in such case.
The line list.push_back(std::make_shared<Test>(Test())); makes a temporary Test and then moves it into the actual Test constructed by std::make_shared<T>. This temporary is then destroyed.
std::make_shared<T> requires the arguments to be used in construction of T. For a default constructed T simply provide no arguments.
The correct use, in this case, is this:
list.push_back(std::make_shared<Test>());
My first constructor edits a member std::map and then calls another constructor. At the end of the first constructor the size of the map is 2, and at the start of the second constructor it's 0. What is causing this?
Here is my header file:
// Test.h
#include <map>
#include <string>
class Test
{
public:
Test(std::string name, int age);
private:
Test();
std::map<std::string, int> myMap_;
}
And here is my code:
// Test.cpp
#include "test.h"
Test::Test()
{
std::cout << myMap_.size() << std::endl; // Outputs 0
}
Test::Test(std::string name, int age)
{
myMap_.insert(name, age);
myMap_.insert("test", 6);
std::cout << myMap_.size() << std::endl; // Outputs 2
Test();
}
EDIT:
And here is my main function:
#include "test.h"
int main()
{
Test t("yo", 4);
return 0;
}
The second constructor inserts 2 elements. So the size is 2.
The first constructor inserts no elements. So the size is 0.
I guess maybe you expect Test(); inside the second constructor to "call the other constructor" for the same object. However this does not happen. Constructors are different to regular functions.
The code Test(); actually means to create a temporary object of type Test, which is initialized by calling the default constructor. Then that object is destroyed immediately, since it was temporary.
Constructors have no name, as far as name lookup is concerned, it's not possible to call them like regular functions. Instead they are invoked when you give the syntax to create an object.
If you want to have some common code that is shared by multiple constructors; you could either put that code in a function that is called by the multiple constructors, or use the delegating constructors feature. In the latter case, the delegation must happen before any statements inside the constructor body are executed.
You are not actually calling the constructor on the same object but create a temporary new one, which then has no name. See it as the same as this:
Test::Test(std::string name, int age)
{
myMap_.insert(name, age);
myMap_.insert("test", 6);
std::cout << myMap_.size() << std::endl; // Outputs 2
Test other = Test(); //you create a new object here
}
In C++11 you can do something like you want to do with this (this is called constructor delegation):
Test::Test(std::string name, int age)
:Test()
{
myMap_.insert(name, age);
myMap_.insert("test", 6);
std::cout << myMap_.size() << std::endl;
}
The difference here though is the Test() constructor will be called before the insert operations on the map.
You are creating two instances of a Test.
The first instance of a Test, which is constructed with the name and age, inserts elements into its myMap_ but the second instance does not.
When you call Test() in the Test(name, age) constructor it is creating a second instance of Test locally using the Test() constructor which does not insert into the map. This second instance would then be almost immediately destroyed (as it is not assigned to anything).
I think you are attempting to use two constructors on the same object, but that is only done for inheriting objects, where each derivation needs to call its own constructor and call its base.
You could create a function and call that instead:
// Test.h
#include <map>
#include <string>
class Test
{
public:
Test(std::string name, int age);
void OutputSize();
private:
Test();
std::map<std::string, int> myMap_;
}
Test::Test(std::string name, int age)
{
myMap_.insert(name, age);
myMap_.insert("test", 6);
OutputSize();
}
void Test::OutputName()
{
std::cout << myMap_.size() << std::endl; // Outputs 2
}
I'm trying to make a kind of screen manager in C++ but I'm getting errors.
With my code below I receive
1>screenmanager.cpp(26): error C2664: 'void std::vector<_Ty>::push_back(_Ty &&)' : cannot convert parameter 1 from 'virtualGameScreen' to 'virtualGameScreen *&&'
1> with
1> [
1> _Ty=virtualGameScreen *
1> ]
1> Reason: cannot convert from 'virtualGameScreen' to 'virtualGameScreen *'
1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>
Errors occur with gameScreen.push_back(gameScreenToAdd);
I get access violation error when adding a reference operator with gameScreenToAdd.
ScreenManager.h
void AddScreen(virtualGameScreen);
void RemoveScreen(virtualGameScreen);
ScreenManager.cpp
std::vector<virtualGameScreen*> gameScreen;
void ScreenManager::Initialize(void)
{
MainMenu menu = MainMenu();
AddScreen(menu);
}
void ScreenManager::AddScreen(virtualGameScreen gameScreenToAdd)
{
gameScreenToAdd.LoadContent();
gameScreen.push_back(gameScreenToAdd);
}
So, I've hit a bit of a wall, any suggestions on how I might fix this?
edit game runs if I change gameScreen.push_back to gameScreen.push_back(new MainMenu()); buut that's not really how I want the function to work
So, the first thing the compiler did is tell you where the problem occurs:
1>screenmanager.cpp(26)
It also told you primarily what the problem is:
Reason: cannot convert from 'virtualGameScreen' to 'virtualGameScreen *'
So - something in your code is providing a "virtualGameScreen" object instance where it was expecting a pointer (denoted by the *). And it's on line 26. The other parts of the error indicate it's the call to push_back. Lets look at line 26:
gameScreen.push_back(gameScreenToAdd);
Yep - you're calling push_back, and you're passing it gameScreenToAdd, which is of type virtualGameScreen. The push_back call is from this vector:
std::vector<virtualGameScreen*> gameScreen;
Your vector expects pointers, so the push_back expects vectors.
HOWEVER: You can't just do this:
gameScreen.push_back(&gameScreenToAdd);
because gameScreenToAdd is a temporary function variable - when you call AddScreen, the original variable is copied into a new, temporary virtualGameScreen for the lifetime of the function call. That means when the program leaves AddScreen the screen whose address you pushed will no-longer exist (the memory is still there, but it has been released and the computer will now proceed to use it for other reasons).
What you'll need to do is change AddScreen to take a pointer.
void ScreenManager::AddScreen(virtualGameScreen* gameScreenToAdd)
{
gameScreenToAdd.LoadContent();
gameScreen.push_back(gameScreenToAdd);
}
Unfortunately, this leaves you open to yet another problem with your code.
void ScreenManager::Initialize(void)
{
MainMenu menu = MainMenu();
AddScreen(menu);
}
This function creates a temporary, local MainMenu object - with a lifetime of the duration of Initialize. Then it creates a second, temporary MainMenu and copies it to menu.
If you write
AddScreen(&menu);
it will work, but it will pass the address of a temporary instance to AddScreen.
As soon as program flow leaves the "Initialize()" function, your value goes away.
It looks like you may have some prior experience with something like Java or C# and are trying to apply previous knowledge to C++.
What you need is a member variable to store "Menu" for the life time of the instance of ScreenManager.
Option 1: Just use a class member variable.
class ScreenManager
{
MainMenu m_menu;
public:
ScreenManager()
: m_menu() // initialize menu while we are initializing.
{}
void Initialize()
{
AddScreen(&m_menu);
}
// ...
};
If you really want to use a pointer, you might do the following:
class ScreenManager
{
MainMenu* m_menu;
public:
ScreenManager()
: m_menu(nullptr) // make sure it's null as soon as the object is created
{}
void Initialize()
{
m_menu = new MainMenu();
AddScreen(m_menu);
}
// but now we have to make sure it is released when we go away
~ScreenManager()
{
if (m_menu)
{
delete m_menu;
m_menu = nullptr;
}
}
};
Option 3: use C++ containers to manage the lifetime of the pointer for you, either std::unique_ptr or std::shared_ptr
---- EDIT ----
Seeing the edit you made while I was writing this, it's a little clearer what you're trying to do. What you probably want is something more like this:
std::vector<std::unique_ptr<virtualGameScreen>> gameScreen;
Consider the following:
Live demo: http://ideone.com/7Th2Uk
#include <iostream>
#include <vector>
class Foo {
const char* m_name;
public:
Foo(const char* name) : m_name(name) { std::cout << "Foo " << m_name << '\n'; }
~Foo() { std::cout << "~Foo " << m_name << '\n'; }
};
int main() {
std::vector<Foo*> foos;
Foo foo("foo");
foos.push_back(new Foo("new"));
return 0;
}
Note that the second foo is never released.
Foo foo
Foo new
~Foo foo
std::unique_ptr is a pointer-container object which will delete the object when the object expires. This makes it suitable for use in a container like std::vector
#include <iostream>
#include <vector>
#include <memory> // for std::unique_ptr
class Foo {
const char* m_name;
public:
Foo(const char* name) : m_name(name) { std::cout << "Foo " << m_name << '\n'; }
~Foo() { std::cout << "~Foo " << m_name << '\n'; }
};
int main() {
std::vector<std::unique_ptr<Foo>> foos;
Foo foo("foo");
foos.emplace_back(new Foo("new"));
return 0;
}
Both objects get cleaned up:
Foo foo
Foo new
~Foo foo
~Foo new
Now you don't need your m_menu at all, you can simply call AddScreen with a 'new MainMenu()' and the pointer will be added to the vector such that when the vector goes out of scope, proper cleanup will happen.
Menu* menu = new MainMenu();
AddScreen(menu);
or
AddScreen(new MainMenu());
In theory what you should really do is ensure that the allocation goes straight into a unique_ptr object so that there's no window for it to get leaked, but teaching the use of std::unique_ptr is beyond the scope of this answer. http://msdn.microsoft.com/en-us/library/hh279676.aspx, http://www.drdobbs.com/cpp/c11-uniqueptr/240002708, etc.
In pre-C++11 code, you might have something like this:
std::vector<virtualGameScreen*> gameScreen;
void ScreenManager::Initialize(void)
{
AddScreen(new MainMenu);
}
void ScreenManager::AddScreen(virtualGameScreen *gameScreenToAdd)
{
gameScreenToAdd->LoadContent();
gameScreen.push_back(gameScreenToAdd);
}
but you would have to have some way to make sure the object got deleted.
With C++11, you would probably want to have the memory managed automatically:
std::vector<std::unique_ptr<virtualGameScreen>> gameScreen;
void ScreenManager::Initialize(void)
{
AddScreen(std::unique_ptr<MainMenu>(new MainMenu));
}
void ScreenManager::AddScreen(std::unique_ptr<virtualGameScreen> gameScreenToAdd)
{
gameScreenToAdd->LoadContent();
gameScreen.emplace_back(std::move(gameScreenToAdd));
}
That's because you did not provide a pointer to the vector (gameScreen), and another issue about the code is that: the paramater will generate a temp object, if just put the address of it the app maybe crash.