1

我想知道关于参数传递 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 是很方便的。如果有什么我可能遗漏或没有想到的,任何建议都非常感谢,谢谢!

4

1 回答 1

0

虽然您可以在 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>Foowith operatorin是什么意思set_foo,但我只是在这里使用了你的代码。

使用可以处理您的设置和清除功能的包装器会更舒服。从这里开始,我什至会使用Resource Acquisition Is Initialization (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,而只使用 a global 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- 方法中。所以,它不可能是完全坏的。

于 2013-05-21T14:37:10.880 回答