我想知道有关参数传递nullptr的C ++ 11最佳实践。我想通过将nullptr传递给已经存在的setter函数来重置类成员对象。举个简单的例子:

#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接口,所以我猜您想实现类似Singleton模式的功能,并带有销毁它的附加功能吗?

在这种情况下,我希望使用两种不同的功能。当您使用不同名称的两个函数时,这是“使界面易于正确使用而难以错误使用”的更好方法(参见Scott Meyers)。如果您将某个功能隐藏在一个不适合其名称的功能中,则从某种意义上说这会使它变得“困难”。

这将转化为

#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中的operatorset_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方法中。因此,它不可能完全不好。

10-08 06:17
查看更多