I'm new to C and I have to following scenario:
main.cpp
#include "Foo.h"
#include "Bar.h"
int main() {
Bar bar{};
auto bar_ptr = std::make_shared<Bar>(bar);
for (int i = 0; i < 10; i ) {
Foo foo{bar_ptr};
}
return 0;
}
I want 10 Instances of Class Foo to share 1 Instance of Class Bar. Each Instance of Class Foo will run in a separate Thread. I want the shared Instance of Class Bar only to be accessed by one Instance of Foo at a time. That's why I wanted to add a std::mutex to Foo. This seems to conflict with std::mutex not being copyable/moveable. What is the correct way to use a mutex with a shared_ptr?
Foo.h
#include <memory>
#include <utility>
#include "Bar.h"
class Foo {
std::shared_ptr<Bar> bar_ptr;
public:
explicit Foo(std::shared_ptr<Bar> bar_ptr){
this->bar_ptr = std::move(bar_ptr);
}
};
Bar.h
#include <mutex>
class Bar {
std::mutex mutex{};
};
CodePudding user response:
std::mutex
is a move-only type, so you can't copy it.
In your main function you are creating a Bar
, and then trying to create a std::shared_ptr
by copying that instance of Bar
.
Instead, just use std::make_shared<Bar>()
to create a shared_ptr
to a bar with the default constructor.
#include "Foo.h"
#include "Bar.h"
int main() {
auto bar_ptr = std::make_shared<Bar>();
for (int i = 0; i < 10; i ) {
Foo foo{bar_ptr};
}
return 0;
}
To clarify, the arguments passed to make_shared
are forwarded to the constructor of the class. If you pass a Bar&
it will try to use the copy constructor.
If you pass nothing it will use the default constructor.
If Bar
s constructor takes arguments in your real use-case, pass the arguments to make_shared
.
#include <memory>
#include <utility>
#include <mutex>
class Bar {
public:
Bar(int i) : value(i) {}
private:
std::mutex mutex{};
int value;
};
class Foo {
std::shared_ptr<Bar> bar_ptr;
public:
// Use the initializer list when possible
// Otherwise we first default-construct then assign
explicit Foo(std::shared_ptr<Bar> ptr) : bar_ptr(std::move(ptr)) {}
};
int main() {
auto bar_ptr = std::make_shared<Bar>(5);
for (int i = 0; i < 10; i ) {
Foo foo{bar_ptr};
}
return 0;
}