我是学习c ++。我看到你通常使用整数来存储一个值,如果我们想表示没有值,那么我们使用-1。例如,在不包含字符串的向量中搜索字符串索引的返回值为-1。在Javascript中很容易:你只是声明它是假的。 我经常遇到两个问题:
我知道javascript是一个不同的世界,但是,例如,这种数据类型的范围在C ++中可以是-1到65534。那么为什么C ++的数据类型不能是数字还是假?还是有一个我忽略的共同编程技巧?
答案 0 :(得分:3)
在 C ++ 17 中有一个可选类型,名为std :: optional。
但我认为你错过了一件事。 C ++一方面是一种非常现代的编程语言,它提供了许多其他现代语言提供的思想。另一方面,它的设计考虑了效率,内存占用效率和速度效率。
例如,从一个字符串中搜索字符串的索引返回 不包含该字符串的向量将为-1。在Javascript中 容易:你只是声明它是假的。我经常遇到两个问题: 如果我打算只使用正值,我会浪费所有可用的 为int分配的范围。所有数字从-2到-32768
那说:
int
值,而是size_t
,这实际上是无符号的。是,-1是使用的文字,但对于无符号类型-1是最大可表示值。除了正好一个值,即最大值,你不会丢失任何东西。 -1 one是表示size_t最大值的最方便的便携方式。在许多实现中,size_t的最大值是18446744073709551615,并且大多数c ++开发人员更喜欢无法搜索长度超过18446744073709551614的字符串(这无论如何都很现实)来摆弄有效可选类型的问题或为标志花费额外的字节
即使size_t最大为65535,65534的大小不足但65535的概率非常接近于零。
答案 1 :(得分:0)
首先,C ++中的函数返回类型是在编译时定义的,这就是为什么你不能做这样的事情
// ...
if (found)
return index;
else
return false;
有几种方法可以解决这个问题。您必须根据您的申请选择。第一个要考虑的是与STL库一致的。容器为其元素提供迭代器,find
返回所请求元素的迭代器。如果未找到,则返回迭代器到容器的past-the-end元素。例如,可以写
// on some container that offers the standard interface
auto it = container.find(value);
if (it == container.end()) {
// not found
}
以上是最干净的解决方案。这就是std::vector
和STL中的每个其他容器发出未找到值的信号。编写这样的代码的主要好处是,您可以将容器替换为任何其他容器,代码仍然有效。或者,如果您使用兼容接口设计自己的容器,则可以无缝地将其插入现有代码中。
然而,在其他情况下,这可能不起作用。例如,您可能只需要实际索引,并且可能很难从非连续容器上的迭代器获取。在这种情况下,您可以使用std::optional
。它要么拥有一个对象,要么为空,并提供bool
转换以便于检查。
std::optional<int> my_find(T value) {
// ...
if (found) // pseudo-condition, depends on the rest of the code
return std::optional<int>(index); // explicit, could be more compact
else
return std::optional<int>(); // default optional is empty
}
// elsewhere
auto i = my_find();
if (!i) {
// not found
}
注意上面的内容,会增加空间开销以跟踪对象是否存在。如果由于任何原因这是不可接受的,你可以采用sentinel值的想法,并创建一个紧凑的可选对象,其中sentinel值在内部用于表示不存在值,并提供一个接口来检查它,也许是一个例外如果用户在对象为空时请求值,则抛出。像
这样的东西template <typename T, T sentinel_value>
class CompactOptional {
private:
T value;
public:
CompactOptional(value = sentinel_value): value(value) {}
operator bool () { return value != sentinel_value; }
// getter and setter according to your needs
}
你必须决定当你试图获得一个不存在的值时会发生什么,然后就是这样。标记值是您不能使用的任何值,如果使用unsigned
,则可能是整数类型的最大值。