C ++ 11 rvalue calls destructor twice

I am trying to create a runner class (run a class with a fixed time frequency) that runs the class on another thread and can be controlled (e.g. pause, resume, stop) from the main thread.

So I want to use C ++ 11 Functor and other functions. But I have a strange problem, the Functor destructor passed to Runner was called twice.

#include <iostream>
#include <chrono>
#include <thread>

using namespace std;

class Runner {
 public:
  typedef function<bool()> fn_t;
  Runner(fn_t &&fn) : fn_(move(fn)), thread_(Thread, ref(*this)) {
    cout << "Runner" << endl;
  }
  ~Runner() {
    cout << "~Runner" << endl;
    thread_.join();
  }
 private:
  fn_t fn_;
  thread thread_;
  static void Thread(Runner &runner) {
    while (runner.fn_()) {
      cout << "Running" << endl;
      this_thread::sleep_for(chrono::milliumseconds(1));
    }
  }
};

class Fn {
 public:
  Fn() : count(0) {
    cout << "Fn" << endl;
  }
  ~Fn() {
    cout << "~Fn" << endl;
  }
  bool operator()() {
    return (++count < 5);
  }
 private:
  int count;
};

int main (int argc, char const* argv[])
{
  Fn fn;
  Runner runner(move(fn));
  return 0;
}

outpus:

Fn
Runner
~Fn
~Runner
Running
Running
Running
Running
Running
~Fn
~Fn

and if I change

Fn fn;
Runner runner(move(fn));

to

Runner runner(Fn());

the program does nothing and stalls. I tried to disable optimization compilation, nothing changes. Any explanation?

How can I fix this or do something in another method? Should I implement this class as std :: async / std :: thread?

Upgrade to Runner runner(Fn())

This statement was interrupted as a function declaration.

Runner runner((Fn())) solved the problem.

. rvalue , rvalue 0. .

#include <iostream>
#include <chrono>
#include <thread>
#include <vector>

using namespace std;

template<typename T, typename... Args>
class Runner {
 public:
  Runner(Args&&... args) : 
      t(forward<Args>(args)...), 
      thread_(Thread, ref(*this)) {
    cout << "Runner" << endl;
  }
  ~Runner() {
    cout << "~Runner" << endl;
    thread_.join();
  }
 private:
  T t;
  thread thread_;
  static void Thread(Runner &runner) {
    while (runner.t()) {
      cout << "Running" << endl;
      this_thread::sleep_for(chrono::milliseconds(100));
    }
  }
};

class Fn {
 public:
  Fn() : count(0) {
    cout << "Fn" << endl;
  }
  ~Fn() {
    cout << "~Fn" << endl;
  }
  bool operator()() {
    return (count++ < 5);
  }
 private:
  int count;
};

int main (int argc, char const* argv[])
{
  //vector<Fn> fns;
  //fns.emplace_back(Fn());
  Runner<Fn> runner;
  return 0;
}

outpus:

Fn
Runner
~Runner
Running
Running
Running
Running
Running
~Fn
+3
2

std::move:

Runner(fn_t &&fn) : fn_(std::move(fn)), thread_(Thread, ref(*this)) {
    /*....*/
}

std::move, const. std::forward:

Runner(fn_t &&fn) : fn_(std::forward<fn_t>(fn)), thread_(Thread, ref(*this)) {
    /*....*/
}
+4

, r-value , . , l- std::function<bool()> Runner.

int main()
{
    Fn fn;
    std::function<bool()> func(fn);
    Runner runner(func); // this is illegal
}

, , , , ​​.

std::function /. , . r, . l-, . Runner -, fontanini.

, , , . , elision, . , , , .

+4

All Articles