class-design - 如何重写在D中使用可变的C++代码?

标签 class-design d mutable

如果您需要在D中重写以下C++代码,您将如何做?

struct A{

    const S* _s;
    B _b;
    C _c;
    mutable C _c1, _c2;

    A(const B& b, const C& c, const S* s){ /*...*/ }

    void compute(const R& r) const
    {
      //...
      _c1 = ...
      _c2 = ...
    }
};

D没有mutable,根据我的经验,它很少在C++中使用。但是,假设出于正确的原因使用了mutable,我在D中的选择是什么?

最佳答案

您有三种选择来处理此问题:

  • 丢弃const。这将使编译器崩溃,但是不能保证您的代码将按预期工作。特别是,如果您从多个线程中在同一对象上调用该函数,那么您将受到数据争夺的摆布。
  • 使用外部数据结构存储可变对象:
    struct A
    {
        static C[const(A)*] _c1s, _c2s;
    
        void compute(ref const(R) r) const
        {
            _c1s[&this] = ...
            _c2s[&this] = ...
        }
    }
    

    我使用&this作为外部哈希表的键,但是使用某种唯一的ID可能会更好。这是一个非常丑陋和棘手的解决方案。我不喜欢另外,请注意,哈希表是线程本地的,因此同一对象在不同线程上将具有不同的值。这对于您的特定应用程序可能是不希望的。
  • 重新考虑如何在D中使用const

    在D中,const是可传递的,并且是按位的,即不支持逻辑const。这样做的目的是保证不会发生并发共享数据写入。即使您的代码在逻辑上可能是const正确的,但如果两个线程试图在同一对象上调用compute,它仍然会中断,因此D不允许这样做,并且不提供任何合法转义(不提供mutable)。

    本质上,仅当它们是按位const时,才应将它们标记为const

    这样的结果是,在D中使用的const比在C++中使用的少得多,因为与逻辑const相比,按位const的使用要少得多。

    例如,考虑一个简单的(无意义的)通用equal函数,该函数告诉您两个对象是否相等:
    bool equal(T)(T lhs, T rhs) { return lhs == rhs; }
    

    注意,我还没有将函数参数标记为const。这是故意的。测试是否相等不需要按位const-它只需要逻辑const,因此在对象上强制执行D的const级别将受到不必要的限制。

    正如jA_cOp所说,D社区认为D中的逻辑常量没有好坏之分。当您尝试像C++的const一样使用D的const时,就会出现问题。它们是不一样的,所以不要以相同的方式使用它们!如果完全有可能某个函数需要使用逻辑const,则不要将它们标记为按位const!
  • 关于class-design - 如何重写在D中使用可变的C++代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8676481/

    相关文章:

    c++ - 从 C++ 源代码创建类图?

    java - Scala:从返回 Seq 的函数返回可变缓冲区

    Scala 使用可变条目填充或制表

    java - 使引用不可变?

    c++ - 初始化另一个类对象中的对象。(在该构造函数上执行一些操作之后。)

    具有通用结构的 C# 类设计

    d - 使用 Dlang 计算目录中的文件

    d - 为什么可以为私有(private)类型创建公共(public)别名?

    class-design - 类设计 'dilemma'

    garbage-collection - D 编程语言是否使用增量垃圾收集器?