Мне было интересно узнать о лучших практиках C ++ 11 в отношении передачи параметров nullptr. Я хочу сбросить объект члена класса, передав nullptr уже существующей функции установки. Для простого примера:
#include "foo.h"
Foo my_foo;
void set_foo(std::shared_ptr<Foo> bar){
my_foo = bar;
}
int main()
{
set_foo(std::make_shared<Foo>());
//do stuff
set_foo(nullptr);
}
Это нормально? Или, или есть лучшие, более предпочтительные методы для сброса my_foo? Я не хотел делать другой метод только для сброса my_foo.
Реальная мотивация в приложении, над которым я работаю, состоит в том, что у меня есть постоянный одноэлементный класс, который используется переменным числом других классов. В целях кодирования этим другим классам удобно просто иметь общий указатель на этот синглтон на время, которое они требуют, и использовать его, а затем отбрасывать / устанавливать значение nullptr, когда им больше не разрешен доступ к нему. Если есть что-то, что я могу пропустить или не думать, любой совет очень признателен, спасибо!
Хотя есть много разных парадигм, которые вы можете использовать с C ++, вы можете использовать методы связать данные и операции вместе?
Но вы, вероятно, не хотите менять Foo
интерфейс, так что я предполагаю, что вы хотите реализовать что-то вроде Синглтон, с дополнительным функционалом для его уничтожения?
Я бы предпочел две разные функции в этом случае. Когда у вас есть две функции с разными именами, это лучший способ «сделать интерфейс простым в использовании, правильно и трудно использовать неправильно» (см. Скотт Мейерс). Если вы скрываете функцию в функции, которая не соответствует ее имени, это делает ее «сложной» в этом смысле.
Это будет переводить на
#include "foo.h"
Foo my_foo;
void set_foo(std::shared_ptr<Foo> bar){
my_foo = bar;
}
void clear_foo(){
my_foo = nullptr;
}
int main()
{
Foo foo.set(std::make_shared<Foo>());
//do stuff
clear_foo();
}
…хотя я не совсем уверен, что вы имеете в виду с назначением shared_ptr<Foo>
к Foo
с operator
в set_foo
Я просто использовал ваш код здесь.
Мне было бы удобнее использовать обертку, которая может обрабатывать ваши сетевые и понятные функции.
И начиная с этого я бы даже зашел так далеко и использовал Приобретение ресурсов — это инициализация (RAII), который вы могли бы представить здесь вот так (только эскиз):
#include "foo.h"
struct FooWrapper {
shared_ptr<Foo> bar_;
FooWrapper() : bar_(nullptr) {}
FooWrapper(shared_ptr<Foo> bar) : bar_(bar) {}
void set(shared_ptr bar<Foo> bar) { bar_ = bar; }
void clear() { bar = nullptr; }
Foo* operator->() { return bar_.get(); }
};
FooWrapper my_foo{};
int main()
{
my_foo.set(std::make_shared<Foo>()); // 1
my_foo->do_stuff();
my_foo.clear(); // clear
my_foo.set(std::make_shared<Foo>()); // 2
} // forgot to clear, doesn't matter FooWrapper takes care of that.
Я думаю, вы можете обойтись без всего FooWrapper
хотя, и просто использовать глобальный shared_ptr<Foo> foo
,
#include "foo.h"
shared_ptr<Foo> my_foo{nullptr};
int main()
{
my_foo.reset( new Foo{} ); // 1
my_foo->do_stuff();
my_foo.reset( new Foo{} ); // 2
my_foo.reset(nullptr); // clear
}
Как вы видете, shared_ptr
использует шаблон для объединения двух различных функций в reset
-метод. Так что это не может быть абсолютно плохо.
Других решений пока нет …