C++中对不可变容器的等效实现

7

最近的讨论引出了这个问题:

C++中是否存在不可变容器?或者,由于C++更喜欢使用迭代器而不是通用容器,是否存在不可变迭代器?

我说的是类似于Guava的ImmutableList或内置的Collections.unmodifiable*方法的等效物。明确地说,这两种类型的集合非常不同-前者本质上是不可变的,而后者只有在获取不可修改引用的演员才是不可变的,但是可能会被访问未包装对象的演员修改。

我想知道是否存在与ImmutableCollection相当的标准化(实际或事实上,如Guava):

  • 任何演员都无法修改的集合。此外,接受此类型的函数提供的文档说明它们不能且不会修改作为参数接收或作为返回值返回的这些集合。

或者像ret ro = Colletions.unmodifiableCollection(orginalCollection)(以及相关方法)一样的东西:

下面是需要翻译的内容:
  • 与上述略有不同,这是原始集合的 视图,任何持有 originalCollection 的人都可以修改它,但持有返回值 ro 的人却不能。通常情况下,它通过在代理中包装原始集合来实现,从而防止任何修改,但也可能有其他实现方式。

我非常了解 const std::iterator 和朋友们,但这是非常不同的 - 它确保调用者可以将对象传递给被调用方,并且该对象不会被修改,但它并不保证被调用方不会修改该对象。

现在我是一个资深的 C++ 用户,虽然过去 5 年里没有用过,但我无法想出明显的等效物。

2个回答

2

0

不,C++中没有这样的容器,但在两个层面上实现这样的容器非常简单... 首先是使用正确的const对象类存储,其次是使用对所需容器的const引用或指针。例如:

#include <iostream>
#include <vector>
#include <string>
#include <memory>

using namespace std;

class Cow {
  public:
  Cow() : name("default") {}
  Cow(string Name) : name(Name) {}

  string shout() const { return name; }

  private:
  string name;
};

int main() {
    vector<unique_ptr<const Cow>> mc;
    Cow mm("Lol");
    mc.push_back(make_unique<const Cow>(Cow()));
    mc.push_back(make_unique<const Cow>(Cow("haha")));
    mc.push_back(make_unique<const Cow>(mm));

    const auto& mcc = mc;  //here, your immutable reference

    for(auto& x : mcc)
        cout << x.get()->shout() << " - - ";
    return 0;
}

我在这里使用 std::unique_ptr,因为使用 vector<const Cow> mc 几乎肯定是无用的。

这部分,const auto& mcc = mc; 从这里开始,将 mcc 作为你的不可变容器... 你不能通过任何合法的手段添加或修改它的元素,除非当然是去掉 const...

这适用于我所知道的所有其他容器。

仍在 Stackoverflow 上,参见 Immutable C++ container classImmutable container with mutable content

附注:此外,如果你想要使用的类是 const 不正确的,请创建一个廉价的包装类,使其成为 const 正确的,然后使用这个包装类。


不,那不是我想要的。mcc对象完全可变,只是不能由获取mcc引用的调用方进行更改!特别是,mcc是可变的,因为mc是可变的。想象一个方法,它接受一个 const Cow参数,假设它是不可变的,并且缓存跨多个cow对象的状态,例如名称。如果更改了cow的名称,则会在上面的示例中失败。 - BeeOnRope
那就是我说需要你进行两个层面的工作的原因... Cow 必须是 const 正确的。如果你不希望在创建后 Cow 发生状态变化,那就不要去改变它... 在我的例子中,绝对没有办法在构造之后改变 Cow 的名称... 如果你的类有可以改变其状态的函数或者可变成员,则必须提供一个 const 正确的包装器... 或者我还是漏掉了什么吗? - WhiZTiM
你仍然缺少一些东西 - Cow 是一个不可变对象(它根本没有可变方法),但是想象一下它是可变的但是符合const - 调用者可以将其作为const Cow传递给任何方法,它仍然是可变的。我的问题特别关于集合,以及C++中是否存在不可变集合。已经清楚地知道可以创建“常量Cow”对象。 - BeeOnRope
好的,但是如果你已经知道Cow是可变的constconst不正确),为什么不提供一个const正确的包装器呢?但是回答你重申的问题。我不知道有“这样”的容器,也没有在C++中遇到过这样的容器,C++中的const概念与Java的不同,据我所知。 - WhiZTiM
让我们在聊天中继续这个讨论 - BeeOnRope
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接