c++ - 修改const shared_ptr&传递的数据可以吗?

标签 c++ c++11 shared-ptr

我遇到过一种情况,我需要通过接受 const shared_ptr 引用的 setter 来设置库对象的属性。这是一个简单的例子:

// library class
class WidgetProxy {
public:
    void setName(const std::shared_ptr<std::string>& name);
    // more methods
};

毫无怀疑,我这样使用它:

WidgetProxy widgetProxy(...);

auto name = std::make_shared<std::string>("Turing");
widgetProxy.setName(name);

// continue using `name`

然后我发现 name setName()之后已变空称呼。幸运的是,库源代码可用,我能够检查其实现。大致内容如下:

class WidgetImpl {
public:
    void setName(std::string name)
    {
        name_ = std::move(name);
    }

private:
    std::string name_;
};

void WidgetProxy::setName(const std::shared_ptr<std::string>& name)
{
    widgetImpl_.setName(std::move(*name));
}

所以setName()移出 shared_ptr 包裹的字符串自 shared_ptr 起正式不再禁止模板参数是 std::string而不是const std::string .

我的问题:

  1. 这是一个正常的设计来实现WidgetProxy::setName()像这样吗?
  2. 当图书馆用户看到 const shared_ptr<T>& 时,他们通常是否应该预料到这种行为?函数参数?

更新:发布的代码片段已大大简化。在库中,有一种不同的类型代替 std::string。我还省略了对指针有效性的检查。

最佳答案

Is it a normal design to implement setName() like this?

这种实现风格是可以的:

void setName(std::string name)
{
    name_ = std::move(name);
}

函数调用首先复制字符串,并将复制的字符串移动到类成员中。生成的代码与传递对字符串的引用,然后复制到数据成员一样高效。

这个不是。我并不不推荐它。

void WidgetProxy::setName(const std::shared_ptr<std::string>& name)
{
    widgetImpl_.setName(std::move(*name));
}

有两个原因。 1:如果不保留指针,为什么需要 std::shared_ptr ? 2:操作的最终结果删除被指针持有的字符串。这会影响shared_ptr的所有其他持有者,其中一些可能需要原始字符串的值。

更正确的编写此函数的方法,以及关联的函数调用:

void WidgetProxy::setName(std::string name)
{
    widgetImpl_.setName(std::move(name));
}

// call as:
if (strPtr)
    proxy.setName(*strPtr);   // with strPtr being a std::shared_ptr<std::string>

Should a library user normally expect such behavior when they see a const shared_ptr& function parameter?

没有。这是一种糟糕的库编码方式。如果调用者出于任何原因希望保留该字符串,他必须使用原始字符串的拷贝创建一个shared_ptr。另外,库代码甚至不检查shared_ptr是否持有有效的指针!非常非常顽皮。

关于c++ - 修改const shared_ptr&传递的数据可以吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45617870/

相关文章:

c++ - 常量成员初始化

c++ - 如何从 vector<shared_ptr> 中删除一个元素

c++ - shared_ptr 与 CComPtr

c++ - tr1::shared_ptr 和 boost::shared_ptr 的区别?

c++ - 在 std::array 中使用时无法从 std::function 构造类

c++ - 初始化忽略构造函数模板

C++,复制构造函数混淆

C++0x 初始化列表示例

c# - protobuf-net 缺少可选字段的 has_ 函数?

java - C++/JNI - 如何访问在 JAVA (Android NDK) 中的 .h 中声明的枚举