如何处理初始值未知的原始类型声明(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> a
和 assert(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);
在某些情况下,我会在不知道其值的情况下声明一个变量,例如:
int a;
if (c1) {
a = 1;
} else if (c2) {
a = 2;
} else if (c3) {
a = -3;
}
do_something_with(a);
无论如何,分配一些明显错误的值(如 -1000
是标准的专业做法(使潜在的错误更容易重现)还是最好不要添加无用的代码,只要没有错误?一方面,消除随机性看起来很合理,另一方面,神奇的甚至“明显错误”的数字不知何故看起来并不吸引人。
在很多情况下,可以在值第一次已知时声明,或者使用三元运算符,但在这里我们需要嵌套,所以也很笨拙。
在块内声明会过早地将变量移出作用域。
或者这种情况会证明以后使用 std::optional<int> a
和 assert(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 ifa
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);