您的位置:首页 > 娱乐 > 八卦 > 怎么制作网页投票软件_在线页面设计工具_北京seo优化多少钱_搜索量用什么工具查询

怎么制作网页投票软件_在线页面设计工具_北京seo优化多少钱_搜索量用什么工具查询

2025/8/7 4:46:53 来源:https://blog.csdn.net/qq_37105120/article/details/143426759  浏览:    关键词:怎么制作网页投票软件_在线页面设计工具_北京seo优化多少钱_搜索量用什么工具查询
怎么制作网页投票软件_在线页面设计工具_北京seo优化多少钱_搜索量用什么工具查询

这个话题是因为,最近一段时间看到有人在问std::optional有什么用,以及不理解为什么要有这个类。所以打算简单介绍一下std::optional,重点讨论返回值相关的内容。

1 std::optional

  • 类模板 std::optional 管理一个可选的包含值,即可能存在也可能不存在的值。
#include <iostream>
#include <optional>
int main()
{std::optional<std::string> a{"abc"};std::optional<std::string> b;if(a) {std::cout << "a = " << *a << "\n";}if(!b) {std::cout << "b is not set\n";}return 0;
}
  • optional 的一个常见用例是可能失败的函数的返回值。
#include <iostream>
#include <optional>std::optional<int> getScore(int id) {// dosomethingbool searchSuccessed = doSearchScoreExist(id);if(searchSuccessed) {int score = doSearchScore(id);return score;}return std::nullopt;
}int main()
{int validId = 2323131;int invalidId = 231310998;if(getScore(valid_id)) {std::cout << "search OK! id = " << validId << "\n";} else {std::cout << "search fail! id = " << validId << "\n";}if(getScore(invalidId)) {std::cout << "search OK! id = " << invalidId << "\n";} else {std::cout << "search fail! id = " << invalidId << "\n";}return 0;
}
  • 它包含有两个优点,一是更好的可读性;二是可更好处理高成本对象(来自于cppreference描述,但存疑)。

对于可读性来说,在c++中为了实现可能存在或者可能不存在的值的功能时。我们可能会选择 创建一个结构体来描述它(坏处是每个类型都需要创建一个这样的结构体)、使用std::pair(坏处是不容易看懂什么意思)、自己造轮子(耗时,还得自己写测试)。
对于高成本对象来说,我未做深入测试,但是从布局来看,它和std::pair<T,bool>相比并没有什么空间和时间的优势。std::optional的可能构成方式:

struct EmptyByte {};
template<class T>
class optional
{bool engaged;union {T value;EmptyByte emptyByte;};
};

2 函数返回值

这里为了方便,我们扩展前面的成绩查询示例:

class ScoreManager {
public:void addScore(int id,int score);int getScore(int id);
};

上述的接口有几个问题,我们分别来看:

2.1 缺少返回值

无论是add还是get,均至少需要对用户返回一个结果,代表着运行正确或者错误。
对于get来说,有的人可能会考虑到score最小值是0,那么我用-1来代表它的结果是有效的。首先,这种使用“魔法值”来判定程序状态的返回值,存在几个重大问题:
      一是对用户来说,极其容易用错,因为他需要阅读你的接口实现或者相关的注释才会知道这件事,更何况大部分情况下都是不读/不写注释的;
      第二是代码出现bug,极其难以定位,假设某个平均成绩计算错误,在复杂场景中,根本无法确定问题;
      第三是影响用户的单元测试,假设其他人调用了getScore,却不知道getScore还有失败的时候,它的单元测试根本覆盖不到这里。

接下来,我们做一定的补全:

class ScoreManager {
public:bool addScore(int id,int score);std::optional<int> getScore(int id);
};

2.2 没有对返回值的处理做限制

因为我们的addScore和getScore都可能会出现失败的情况,用户有可能会不对这种失败的情况做验证,因此,我们需要用户必须去处理返回值。我们期望的是这样:

void good()
{auto ret = scoreManager.getScore(0);if (!ret) {// dosomething}if(!scoreManager.addScore(1,0)) {// dosomething}
}// 我们期望没有处理返回值时,报错或者警告
void bad()
{scoreManager.addScore(10,10);scoreManager.getScore(5);
}int main()
{ScoreManager scoreManager;good();bad();return 0;
}

在这种情况下,我们可以使用c++中的[[nodiscard]]属性,该属性的作用是:
如果将声明了nodiscard的函数的返回值忽略,则编译器发出警告。

我们更新一下ScoreManager:

class ScoreManager {
public:[[nodiscard]]bool addScore(int id,int score);[[nodiscard]]std::optional<int> getScore(int id);
};

2.3 没有失败时的报错信息

对于getScore接口来说,我们期望在它错误时能反馈一些信息给用户,以提示它的错误原因。这时不得不夸一下Rust的Result了,来看看它是如何做的:

fn div(x: f64, y: f64) -> Result<f64, MathError> {if y == 0.0 {// 此操作将会失败,那么(与其让程序崩溃)不如把失败的原因包装在// `Err` 中并返回Err(MathError::DivisionByZero)} else {// 此操作是有效的,返回包装在 `Ok` 中的结果Ok(x / y)}
}

上述的接口对用户来说,如果运行正确,则返回结果;否则,返回错误的原因。在c++当中没有自带这样的接口,不过,我们可以自己简单的实现一下:

template<typename V,typename E>
class Reust
{
private:std::optional<V> value;std::optional<E> error;Result(const std::optional<V> &value,const std::optional<E> &error):value(value),error(error){}
public:static Reust<V,E> Ok(V &&v) {return Result(std::forward<V>(v),std::nullopt);}static Reust<V,E> Err(E &&e) {return Result(std::nullopt,std::forward<E>(e));}bool isError() {return error.has_value();}const V & getValue() {return value.value();}const V & getError() {return error.value();}
};

到这里,我们造好了这个玩具轮子,接下来更新ScoreManager:

class ScoreManager {
public:enum class ManagerError{...};[[nodiscard]]std::optional<ManagerError> addScore(int id,int score);[[nodiscard]]Reust<int,std::ManagerError> getScore(int id);
};

因为对于addScore来说的话,它仅需要错误时的原因,所以采取了std::optional;对于getScore来说,我们支持了返回值和错误信息两点。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com