Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用附加状态信息扩展基元类型以用于特殊情况_C++ - Fatal编程技术网

C++ 使用附加状态信息扩展基元类型以用于特殊情况

C++ 使用附加状态信息扩展基元类型以用于特殊情况,c++,C++,我正在寻找一种通过一些状态信息来扩展int变量的方法,这些状态信息很少使用,而且大多数情况下只计算int值。这就是为什么我希望避免使用带有其他布尔成员的结构 相关的附加属性最多为5到6个附加属性,例如NULL、UNDEFINED、NAN,其中只有一个可以为true 想法: int指针是为一个附加属性执行此操作的一种方法:nullptr是int变量可以接受的一个附加值。但在这种情况下,我不能有更多的例外状态 另一种选择是使用一些我不希望使用的神奇值,例如UNDEFINED=std::numeri

我正在寻找一种通过一些状态信息来扩展
int
变量的方法,这些状态信息很少使用,而且大多数情况下只计算int值。这就是为什么我希望避免使用带有其他布尔成员的结构

相关的附加属性最多为5到6个附加属性,例如NULL、UNDEFINED、NAN,其中只有一个可以为true

想法:

  • int指针是为一个附加属性执行此操作的一种方法:nullptr是int变量可以接受的一个附加值。但在这种情况下,我不能有更多的例外状态

  • 另一种选择是使用一些我不希望使用的神奇值,例如
    UNDEFINED=std::numeric\u limits::min()
    MISSING=std::numeric\u limits::min()+1
    等等

问题:有没有更好的方法来实现这一点(需要最少的额外内存)


子问题:如果我能确定值是否在编译时属于例外情况,是否有一种不使用额外内存的好方法来执行此操作?

最好的替代方法不是使用int,而是使用其他类型–您建议使用的
int*
也属于这一类。当然,这种包装类型可以重载各种运算符,以便访问底层整数值。定义一个新类型(或利用现有的标准库类型)是内存的最佳条件,因为您可能只会将每个整数的大小增加一倍(例如,现在您可能有整数+枚举(由int或更小的整数支持)+可能有填充)。根据您的整数大小,即使是指针也可能有更多的内存开销

如果只有少数整数具有额外的状态,并且这些整数不会被复制或移动,那么可以将状态存储在外部,在从整数标识到状态的映射中。也就是说,我们使用指向整数对象的指针作为键。每一个具有额外状态的整数,此映射的内存开销将比其他映射高得多,但根据您的使用模式,这可能是最紧凑的解决方案。显然,这里存在内存泄漏的机会,因此您可能应该将整数封装在自定义类型中,以在销毁时删除任何映射条目。大致如下:

enum class IntStatus { IS_NAN, IS_MISSING };

class IntWithExternalStatus {
public:
  explicit IntWithExternalStatus(int x = 0) : m_value{x} {}
  explicit IntWithExternalStatus(IntStatus s) : m_value{} { s_status.insert({this, s}); }
  ~IntWithExternalStatus() { m_status.erase(this); }

  operator int& () { return m_value; }
  operator int  () const { return m_value; }
  bool is_valid() const { return s_status.find(this) == s_status.end(); }
  bool is_nan() const {
    auto it = s_status.find(this);
    return it != s_status.end() && it->second == IntStatus::IS_NAN;
  }
  bool is_missing() const {
    auto it = s_status.find(this);
    return it != s_status.end() && it->second == IntStatus::IS_MISSING;
  }
private:
  static std::unordered_map<IntWithExternalStatus const*, IntStatus> s_status;
  int m_value;
};
由于对齐问题,这可能导致内存布局比定义一个int和status组合对象更紧凑

为状态使用特殊值是一个没有空间开销的简单解决方案,但有一个巨大的缺点:对这些整数进行任何运算都会删除状态并产生虚假值。您将需要大量的运行时检查来防止这种情况,最好将其封装在单独的类型中


关于编译时子问题,这取决于您对内存使用的定义。例如,您可以使用模板元编程,根据编译时值选择
int
InvalidInt
类型,其中InvalidInt是一种空对象模式。但是,这将为所有实例化的模板生成专用代码。特别是,使用status int的代码也必须模板化。如果在同一时间有许多状态int,并且它们都具有相同的状态,这可能会减少总内存使用量,但在其他情况下不太可能有帮助。

未定义和丢失之间的区别是什么?AFAIK整数不能是NAN。要么你按照你说的做,使用魔法值,要么你需要更多的位。如果不以这种或那种方式使用更多内存,就无法存储其他信息。关于存储这些额外信息的位置/方式,有很多选项。@Mat yes,这很有意义。@NathanOliver undefined将在写入DB期间导致空值,如果程序员试图将数据存储在DB中,missing将抛出错误。您是否在寻找
std::any
std::optional
int m_foo;
int m_bar;
IntStatus m_foo_status;
IntStatus m_bar_status;