【问题标题】:c++98 struct default to zero except one valuec++98 struct 默认为零,除了一个值
【发布时间】:2017-10-08 02:08:55
【问题描述】:

这当然与已回答的许多其他问题有关,但我无法从这些问题中得出针对我的具体案例的答案,主要是因为我实际上不是程序员;我只是一个碰巧要写一些代码的工程师。

情况如下:

  • 我有一堆变量要收集在一起,可能会收集到一个结构中。
  • 除了两个我想初始化为零;需要将两个特定变量(恰好不是前两个)初始化为一个。
  • 实际名称是唯一且足够有意义的,因此使用向量是不合适的,而且其中也有一些双精度词。为了清楚起见,我将下面的示例保持简单。
  • 由于我正在从事的项目,我一直坚持使用 C++98,因此即使 C++11 有更优雅的解决方案,它们也不适合我。

我正在考虑结构本身的这些方面:

struct allFlags
{
    int flagAA;
    int flagAB;
    int flagAC;
    int flagAD;
    int flagAE;
    // ...
    // there's about 100 variables total
    // ...
    int flagZZ;
};

我想将所有标志初始化为 0,除了 flagADflagAE,它们应该是 1。

首先,我不确定我应该使用typedef struct allFlags 还是struct allFlags。接下来,我不确定是否应该创建一个构造函数(我认为只有在没有typedef 的情况下才适用?)或者在我实例化结构时进行默认设置。我见过这样的事情(将放在结构定义中):

    allFlags() : flagAD(1), flagAE(1) { /*not sure of I'd need anything here*/ }

但我不想在构造函数主体中按名称单独列出所有其他 ~98 个变量以将它们设置为零。我也看到了使用 memset 的东西,这可能会有所帮助,但我不确定最好的方法。

最后一个额外的相关问题是如何实际声明我的结构的一个实例(这会产生我想要的初始值)。看起来有时 struct 是用 new 关键字实例化的,有时它更像是一种基本数据类型,即我在搜索中看到了这两种:

allFlags flagset1;
flagset2 = new allFlags;

我还看到了这样的语法,而不是使用构造函数:

allFlags flagset3 = {}; // to zero all fields first
flagset3.flagAD = 1;
flagset3.flagAE = 1;

但我宁愿保持实例化尽可能简洁。

请原谅这个问题。我在提问之前尝试过做功课,但我的 C++ 知识充其量只是平庸,所以我发现一些看似相关的答案我要么没有完全理解,要么只是提出了更多问题。

【问题讨论】:

  • 结构是 POD 类型吗?
  • C++ 使typedef struct 模式变得不必要。 struct allFlags 就足够了。
  • 数组不应该解决这些类型的问题吗?我错过了什么?如果有 200、300 或 1,000 个标志,您会创建 200、300 等单独的变量吗?
  • 我认为 OP 希望为每个人指定一个特定的唯一名称,因此数组不起作用。但是,您的观点是正确的,@PaulMcKenzie
  • 您仍然可以使用数组。只需使用枚举、常量等来表示您想要的标志。 const int AA = 0; const int AB = 1;...int flags[100]; flags[AA] = 1;等,初始化只进行一次,没有100个单独的变量。基本上没有理由我可以想到创建 100 个或更多相同类型的单独变量,在相同的上下文中使用(都是 int 并且都表示某种标志)。

标签: c++ struct default-value


【解决方案1】:

如果您对使用模板感到满意,您可以使用类模板来自动对allFlags 的所有成员变量进行干净初始化。

// class template to help initialize members cleanly.
template <typename T>
struct flag
{
   // Constructors
   flag() : val(0) {}
   flag(T const& v) : val(v) {}

   // Automatic cast operators to T
   operator T& () { return val; }
   operator T const& () const { return val; }

   // Comparison operators
   bool operator==(flag const& rhs) const { return val == rhs.val; }
   bool operator!=(flag const& rhs) const { return val != rhs.val; }
   bool operator<(flag const& rhs) const { return val < rhs.val; }

   T val;
};

typedef flag<int> IntFlag;
typedef flag<double> DoubleFlag;

struct allFlags
{
   // Initialize all flags bug flagAD to zero.
   allFlags() : flagAD(1) {}

   IntFlag flagAA;
   IntFlag flagAB;
   IntFlag flagAC;
   IntFlag flagAD;
   IntFlag flagAE;
   IntFlag flagZZ;
};

#include <iostream>

int main()
{
   allFlags f;
   std::cout << f.flagAA << " " << f.flagAD << std::endl;
}

输出:

0 1

【讨论】:

  • 这个提议的一个变体,加上对一组标志使用枚举,似乎是获胜的组合。它比我预期的要多,但从用户的角度来看,它工作得很好。
  • @Mike,很高兴我能提供帮助。使用enums 总是在我脑海中引发危险信号。如果您想查看enum 是否可以被其他东西替换,或者您想获得有关如何改进代码的一般反馈,请访问codereview.stackexchange.com 并在那里发布问题。在创建帖子之前,请务必阅读 their guidelines on what to ask
  • @R Sahu - 根据您的建议,我已在 codereview 上征求过一些建议。
【解决方案2】:

你自己的问题回答得很好:

allFlags flagset3 = {}; // to zero all fields first
flagset3.flagAD = 1;
flagset3.flagAE = 1;

它很干净,并且非常清楚您的意图。稍后,当其他人必须阅读您的代码时,他们会准确地理解您要做什么。

类似于你在设备驱动程序编程中看到的:

registerX = 0 | 1 << BIT2 | 1 << BIT3;

【讨论】:

  • 致OP:如果多处使用相同的三行,最好放在一个函数中使用函数。
  • "非常清楚你的意图" - 仅当你的意图是要求allFlags 的每个客户端都知道如何初始化allFlags 的实例而不是封装该信息在它所属的构造函数中。
  • 正如 Obvlious 船长所说,每次都需要这三行代码,而不是一行。 allFlags 的实例化发生在客户包装代码中,因此我强烈倾向于以客户不需要做任何特殊事情的方式来处理它。
  • 那么你肯定想创建一个设置变量的构造函数。 R Sahu 建议的另一种选择是创建一个初始化函数。
猜你喜欢
  • 2015-10-01
  • 1970-01-01
  • 2015-05-24
  • 2015-10-28
  • 1970-01-01
  • 2019-10-03
  • 2010-09-26
  • 1970-01-01
  • 2020-10-18
相关资源
最近更新 更多