如何处理初始值未知的原始类型声明(C++)?

How to deal with declaration of the primitive type without the initial value known (C++)?

在某些情况下,我会在不知道其值的情况下声明一个变量,例如:

int a;
if (c1) {
  a = 1;
} else if (c2) {
  a = 2;
} else if (c3) {
  a = -3;
} 
do_something_with(a);

无论如何,分配一些明显错误的值(如 -1000 是标准的专业做法(使潜在的错误更容易重现)还是最好不要添加无用的代码,只要没有错误?一方面,消除随机性看起来很合理,另一方面,神奇的甚至“明显错误”的数字不知何故看起来并不吸引人。

在很多情况下,可以在值第一次已知时声明,或者使用三元运算符,但在这里我们需要嵌套,所以也很笨拙。

在块内声明会过早地将变量移出作用域。

或者这种情况会证明以后使用 std::optional<int> aassert(a) 是合理的,确保我们有值吗?

编辑:如果突然所有 3 个条件都为假且“绝对不会发生”,那么我所说的错误就会发生。

在我看来,最安全的选择是,如果你不想要这个其他值(它只是没用),那么它可能会导致非常微妙的错误,这可能很难找到。因此,当不满足任何条件时,我会提出期望:

int get_init_value(bool c1, bool c2, bool c3) {
    if (c1) { return 1; }
    else if (c2) { return 2; }
    else if (c3) { return -3; }
    throw std::logic_error("noone of conditions to define value was met");
}

这样我们就可以避免得到一些奇怪的值,这些值实际上与我们的代码匹配,但无论如何它们都会编译(调试可能会花费很多时间)。我认为这比仅仅给它分配一些明显错误的值要好得多。

据我所知,最流行和最安全的方法是使用内联 lambda 调用。请注意 if 应该是详尽无遗的(我添加了 SOME_DEFAULT_VALUE 作为占位符)。我想如果你不知道在最终 else 块中放什么,你应该考虑几个选项:

  • 使用 optional 并将 none 放入 else,
  • 抛出描述问题的异常,
  • 如果从逻辑上讲这种情况永远不会发生,请输入 assert
const int a = [&] {
  if (c1) {
    return 1;
  } else if (c2) {
    return 2;
  } else if (c3) {
    return -3;
  } else {
    return SOME_DEFAULT_VALUE;
  }
}();
do_something_with(a);

在初始化逻辑在某处重复的情况下,您可以简单地将 lambda 提取到命名函数,如其他答案所建议的那样

基于意见的答案!

我知道这个例子是一个真实的、更复杂的例子的简化,但恕我直言,现在这种设计问题似乎更经常出现,人们有时会把它复杂化。

变量的全部目的不就是保存一些值吗?那么这个变量的默认值不是也是可行的吗?

那么问题到底出在哪里:

int a = -1000; // or some other value meant to used for undefined
if (c1) {
  a = 1;
} else if (c2) {
  a = 2;
} else if (c3) {
  a = -3;
} 
do_something_with(a);

它简单易读...没有 lambda、异常和其他使代码变得不必要复杂的东西...

或喜欢:

int a;
if (c1) {
  a = 1;
} else if (c2) {
  a = 2;
} else if (c3) {
  a = -3;
} else {
  a = -1000;  // default for unkown state
}
do_something_with(a);

您可以引入一个常量 const int undefined = -1000; 并使用该常量。
或者枚举,如果 c1、c2、c3 是某种状态(很可能是)...
如果其他地方不需要变量,您可以重新排列代码以删除该变量。

if (c1) {
  do_something_with(1);
} else if (c2) {
  do_something_with(2);
} else if (c3) {
  do_something_with(-3);
} 

我知道你的真实代码比提供的大纲复杂得多,但恕我直言,这里的主要问题是

should we do_something_with(a) at all if a is undefined,

而不是

what the initial value should be.

并且解决方案可能是向实际参数 a 显式添加一些状态标志,例如 a_is_defined,而不是使用魔法常量。

int a = 0;
bool a_is_defined = false;

当您根据 c... 条件设置它们并将它们传递给 do_something() 时,您将能够明确区分特定 if(a_is_defined) {...} 路径和默认路径 (错误处理?)else {...}.

或者甚至提供单独的例程来显式处理更早一级的两个路径:if(a_is_defined) do_someting_with(a); else do_something_else();.

我会引入一个默认值。我通常为此使用类型的最大值。

最短的你可以用这样的三元运算符来做到这一点:

#include <climits>

int a = c1 ? 1 : c2 ? 2 : c3 ? -3 : INT_MAX;

do_something_with(a);