- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
#include <iostream>
#include <optional>
// 定义一个没有默认构造函数的类
class MyClass {
public:
explicit MyClass(int value) : data(value) {}
~MyClass() {}
int getData() const {
return data;
}
private:
int data;
};
// 输出 std::optional 是否包含值
void check_optional_value(std::optional<MyClass>& opt) {
if (opt) {
std::cout << "Value present: " << opt->getData() << std::endl;
} else {
std::cout << "No value present." << std::endl;
}
}
int main() {
// 创建一个没有值的 std::optional<MyClass>
std::optional<MyClass> opt1;
check_optional_value(opt1);
// 创建一个有值的 std::optional<MyClass>
std::optional<MyClass> opt2{MyClass(42)};
check_optional_value(opt2);
// 尝试通过 emplace 添加值
opt1.emplace(24);
check_optional_value(opt1);
// 尝试通过 operator= 添加值
opt1 = MyClass(56);
check_optional_value(opt1);
return 0;
}
输出: Size of i: 4 bytes Size of St8optionalIiE: 8 bytes Size of 7MyClass: 4 bytes Size of St8optionalI7MyClassE: 8 bytes 。
然而,可选对象并不是简单的等价于附加了bool标志的内含对象。例如,在没有值的情况下,将不会调用内含对象的构造函数(通过这种方式,没有默认构造函数的内含类型也可以处于有效的默认状态).
3.语义 和 std::variant<>、std::any一样,可选对象有值语义。也就是说,拷贝操作会被实现为深拷贝:将创建一个新的独立对象,新对象在自己的内存空间内拥有原对象的标记和内含值(如果有的话)的拷贝。拷贝一个无内含值的 std::optional<>的开销很小,但拷贝有内含值的 std::optional<>的开销约等于拷贝内含值的开销。另外,std::optional<>对象也支持 move语义.
4.应用 (1)std::optional<>模拟了一个可以为空的任意类型的实例。它可以被用作成员、参数、返回值等。 下面的示例程序展示了将 std::optional<>用作返回值的一些功能:
#include <optional>
#include <string>
#include <iostream>
// 如果可能的话把string转换为int:
std::optional<int> asInt(const std::string& s)
{
try {
return std::stoi(s);
}
catch (...) {
return std::nullopt;
}
}
int main()
{
for (auto s : {"42", " 077", "hello", "0x33"}) {
// 尝试把s转换为int,并打印结果:
std::optional<int> oi = asInt(s);
if (oi.has_value()) {
std::cout << "convert '" << s << "' to int: " << oi.value() << "\n";
}
else {
std::cout << "can't convert '" << s << "' to int\n";
}
}
}
(2) 另一个使用 std::optional<>的例子是传递可选的参数和设置可选的数据成员:
#include <optional>
#include <string>
#include <iostream>
class Name
{
private:
std::string first;
std::optional<std::string> middle;
std::string last;
public:
Name (std::string f, std::optional<std::string> m, std::string l)
: first{std::move(f)}, middle{std::move(m)}, last{std::move(l)} {
}
friend std::ostream& operator << (std::ostream& strm, const Name& n) {
strm << n.first << ' ';
if (n.middle) {
strm << *n.middle << ' ';
}
return strm << n.last;
}
};
int main()
{
Name n{"Jim", std::nullopt, "Knopf"};
std::cout << n << '\n';
Name m{"Donald", "Ervin", "Knuth"};
std::cout << m << '\n';
}
5.std::optional<>类型和操作 (1)std::optional<>类型标准库在头文件 中以如下方式定义了 std::optional<>类: namespace std { template class optional; } 另外还定义了下面这些类型和对象: • std::nullopt_t类型的 std::nullopt,作为可选对象无值时候的“值”。 • 从 std::exception派生的 std::bad_optional_access异常类,当无值时候访问值将会抛出该异常。 可选对象还使用了 头文件中定义的 std::in_place对象(类型是 std::in_place_t)来支持用多个参数初始化可选对象(见下文)。 (2)std::optional<>的操作 表std::optional的操作列出了 std::optional<>的所有操作:
#include <iostream>
#include <optional>
#include <variant>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <functional>
#include <cassert>
#include <complex>
// 使用命名空间简化代码
using namespace std::string_literals;
// 示例 1:构造 std::optional
void construct_optional() {
std::optional<int> o1; // 不含有值
assert(!o1.has_value());
std::optional<int> o2(std::nullopt); // 显式表示不含有值
assert(!o2.has_value());
std::optional o3{42}; // 推导出 std::optional<int>
assert(o3.has_value());
assert(*o3 == 42);
std::optional o4{"hello"}; // 推导出 std::optional<const char*>
assert(o4.has_value());
assert(*o4 == "hello");
std::optional o5{"hello"s}; // 推导出 std::optional<std::string>
assert(o5.has_value());
assert(*o5 == "hello");
// 用多个参数初始化可选对象
std::optional<std::complex<double>> o6{std::in_place, 3.0, 4.0};
assert(o6.has_value());
assert(o6->real() == 3.0 && o6->imag() == 4.0);
// 使用 std::make_optional
auto o13 = std::make_optional(3.0); // std::optional<double>
assert(o13.has_value());
assert(*o13 == 3.0);
auto o14 = std::make_optional("hello"); // std::optional<const char*>
assert(o14.has_value());
assert(*o14 == "hello");
auto o15 = std::make_optional<std::complex<double>>(3.0, 4.0);
assert(o15.has_value());
assert(o15->real() == 3.0 && o15->imag() == 4.0);
}
// 示例 2:访问值
void access_optional_value() {
std::optional<std::pair<int, std::string>> o{std::make_pair(42, "hello")};
assert(o.has_value());
assert(o->first == 42);
assert(o->second == "hello");
std::optional<std::string> o2{"hello"};
assert(o2.has_value());
assert(*o2 == "hello");
// 当没有值时访问会导致未定义行为
o2 = std::nullopt;
assert(!o2.has_value());
// std::cout << *o2 << std::endl; // 未定义行为
}
// 示例 3:使用 value_or
void use_value_or() {
std::optional<std::string> o{"hello"};
std::cout << o.value_or("NO VALUE") << std::endl; // 输出 "hello"
o = std::nullopt;
std::cout << o.value_or("NO VALUE") << std::endl; // 输出 "NO VALUE"
}
// 示例 4:比较
void compare_optionals() {
std::optional<int> o0;
std::optional<int> o1{42};
assert(o0 == std::nullopt);
assert(!(o0 == 42));
assert(o0 < 42);
assert(!(o0 > 42));
assert(o1 == 42);
assert(o0 < o1);
assert(!(o0 > o1));
std::optional<unsigned> uo;
assert(uo < 0);
assert(uo < -42);
std::optional<bool> bo;
assert(bo < false);
std::optional<int> o2{42};
std::optional<double> o3{42.0};
assert(o2 == 42);
assert(o3 == 42);
assert(o2 == o3);
}
// 示例 5:修改值
void modify_optional_value() {
std::optional<std::complex<double>> o; // 没有值
std::optional<int> ox{77}; // optional<int>,值为77
o = 42; // 值变为 complex(42.0, 0.0)
assert(o.has_value());
assert(o->real() == 42.0 && o->imag() == 0.0);
o = std::complex<double>{9.9, 4.4}; // 值变为 complex(9.9, 4.4)
assert(o.has_value());
assert(o->real() == 9.9 && o->imag() == 4.4);
o = ox; // OK,因为 int 转换为 complex<double>
assert(o.has_value());
assert(o->real() == 77.0 && o->imag() == 0.0);
o = std::nullopt; // o 不再有值
assert(!o.has_value());
o.emplace(5.5, 7.7); // 值变为 complex(5.5, 7.7)
assert(o.has_value());
assert(o->real() == 5.5 && o->imag() == 7.7);
o.reset(); // o 不再有值
assert(!o.has_value());
o = std::complex<double>{88.0, 0.0}; // OK:值变为 complex(88.0, 0.0)
assert(o.has_value());
assert(o->real() == 88.0 && o->imag() == 0.0);
o = std::complex<double>{1.2, 3.4}; // OK:值变为 complex(1.2, 3.4)
assert(o.has_value());
assert(o->real() == 1.2 && o->imag() == 3.4);
}
// 示例 6:使用 lambda 初始化 set
void initialize_set_with_lambda() {
auto sc = [](int x, int y) {
return std::abs(x) < std::abs(y);
};
std::optional<std::set<int, decltype(sc)>> o8{std::in_place,
std::initializer_list<int>{4, 8, -7, -2, 0, 5},
sc};
assert(o8.has_value());
assert(o8->size() == 6);
}
int main() {
construct_optional();
access_optional_value();
use_value_or();
compare_optionals();
modify_optional_value();
initialize_set_with_lambda();
return 0;
}
6.注意 (1)value()和 value_or() value()和 value_or()之间有一个需要考虑的差异:4 value_or()返回值,而 value()返回引用。这意味着如下调用: std::cout << middle.value_or(""); 和: std::cout << o.value_or("fallback"); 都会暗中分配内存,而 value()永远不会。 然而,当在临时对象 (rvalue)上调用 value_or()时,将会移动走内含对象的值并以值返回,而不是调用拷贝函数构造。这是唯一一种能让 value_or()适用于 move-only的类型的方法,因为在左值 (lvalue)上调用的 value_or()的重载版本需要内含对象可以拷贝。 因此,上面例子中效率最高的实现方式是: std::cout << o ? o‐>c_str() : "fallback"; 而不是: std::cout << o.value_or("fallback"); value_or()是一个能够更清晰地表达意图的接口,但开销可能会更大一点。 (2)bool 类型或原生指针的可选对象 将可选对象用作 bool值时使用比较运算符会有特殊的语义。如果内含类型是 bool或者指针类型的话这可能导致令人迷惑的行为。例如: std::optional ob{false}; // 值 为false if (!ob) ... // 返 回false if (ob == false) ... // 返 回true std::optional<int*> op{nullptr}; if (!op) ... // 返 回false if (op == nullptr) ... // 返 回true 。
最后此篇关于C++17新特性探索:拥抱std::optional,让代码更优雅、更安全的文章就讲到这里了,如果你想了解更多关于C++17新特性探索:拥抱std::optional,让代码更优雅、更安全的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!