表示无效值
1 在C++中如何表示无效值?
无效值?
答:可以理解成不是我们希望的值,或者说返回值是位于解空间外的值。比如,我们希望除法分母不为0,开平方不能小于0等等
如何表示无效值?
答:下面是我们常见的手法
1. 发现错误,就抛出异常
2. 为无效值增加“哨兵”,比如NULL,EOF,string::pos,-1等等
上述做法的问题?
- 在要求苛刻的场景下,抛出异常是不能忍受的
- 遇到无法表示的”哨兵“
2 boost使用optional表达无效值,已被引入C++17
把optional理解成指针!!!.
下面是思维导图
下面分享重要的内容
2.1 创建optional
无效值常量
boost::none
创建未初始化值的两种方法
// 创建空对象的两种方式
boost::optional<int> op0;
boost::optional<int> op1(boost::none);
assert(op0 == op1 && !op0);
2.2 按条件初始化
条件不满足,初始化为无效值,否则是初始化值
下面是一个除法,排除分母为0的案例
boost::optional<double> reciprocal(int x) {
return boost::optional<double>(x != 0, 1.0 / x); // 满足不为0,则求倒数
}
// main
boost::optional<double> d1 = reciprocal(0);
if (!d1)
{
std::cout << "no result" << std::endl;
}
2.3 请把optional当成指针
boost::optional<std::string> ops("test");
// 下面的输出都是test
std::cout << *ops << std::endl;
std::cout << ops.get() << std::endl;
// 就地创建一个字符串,这里只用前三个构造
ops.emplace("monado", 3);
assert(*ops == "mon");
2.4 关于optional的疑惑
下面的代码,能不能实现目标–判断b是否是false
optional<bool> b(false);
if(!b)
cout << "false" << endl;
答:不能,!b表示b是否已经初始化,而不是判断内容为false
正确的做法,首先b已经初始化而且值为false
if(b && !*b)
cout << "false" << endl;
3 其他
源码中,有大量typedef,这样代码可读性更强,
// 类型名
#define BOOST_DEDUCED_TYPENAME typename
其中,下面包含了绝大部分,可以借鉴
value_type - ----> T
reference_type ----> T&
reference_const_type/argument_type ----> T cosnt &
rval_reference_type ----> T&&
pointer_const_type ----> T const*
typedef optional<T> this_type ;
typedef BOOST_DEDUCED_TYPENAME base::value_type value_type;
typedef BOOST_DEDUCED_TYPENAME base::reference_type reference_type;
typedef BOOST_DEDUCED_TYPENAME base::reference_const_type reference_const_type;
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
typedef BOOST_DEDUCED_TYPENAME base::rval_reference_type rval_reference_type;
typedef BOOST_DEDUCED_TYPENAME base::reference_type_of_temporary_wrapper reference_type_of_temporary_wrapper;
#endif
typedef BOOST_DEDUCED_TYPENAME base::pointer_type pointer_type;
typedef BOOST_DEDUCED_TYPENAME base::pointer_const_type pointer_const_type;
typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type;