0Pricing
C++ Academy · 课时

std::variant

类型安全的联合体

std::variant 是 CoddyKit 上的免费 C++ Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C++ Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C++ Academy 课程共包含 4 节课。

类型安全的联合体

std::variant 从固定的类型列表中恰好保存一个值,并且记住当前保存的是哪一种类型。请包含 <variant> 以使用它。

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 10;
    std::cout << std::get<int>(v) << "\n";
}

赋予不同类型的值

您可以将 variant 重新赋值为其任意一种备选类型。它会自动更新当前活动的备选类型。

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 5;
    v = 3.14; // now holds a double
    std::cout << std::get<double>(v) << "\n";
}

检查活动类型

std::holds_alternative<T>(v) 会告诉您该 variant 当前是否保存着类型 T。

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 2.0;
    std::cout << std::holds_alternative<double>(v) << "\n";
    std::cout << std::holds_alternative<int>(v) << "\n";
}

index() 函数

v.index() 返回活动类型在类型列表中的从零开始的位置。

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double, char> v = (char)65;
    std::cout << v.index() << "\n"; // 2
}

使用 std::get 安全访问

如果 T 处于活动状态,std::get<T> 会返回其值;否则会抛出 std::bad_variant_access。不会静默地产生垃圾值。

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 7;
    try {
        std::cout << std::get<double>(v) << "\n";
    } catch (const std::bad_variant_access& e) {
        std::cout << "wrong type!\n";
    }
}

不抛出异常的 get_if

如果 T 处于活动状态,std::get_if<T>(&v) 会返回指向该值的指针;否则返回 nullptr。这非常适合无分支检查。

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v = 9;
    if (auto p = std::get_if<int>(&v))
        std::cout << "int " << *p << "\n";
}

默认构造

默认构造的 variant 保存其第一个类型的值初始化版本。请合理安排类型顺序,使第一个类型成为合适的默认类型。

#include <iostream>
#include <variant>
int main() {
    std::variant<int, double> v; // holds int 0
    std::cout << std::get<int>(v) << "\n";
}

存储字符串

与原始联合体不同,variant 可以安全地保存 std::string 等非平凡类型;生命周期由它替您管理。

#include <iostream>
#include <string>
#include <variant>
int main() {
    std::variant<int, std::string> v = std::string("hello");
    std::cout << std::get<std::string>(v) << "\n";
}

作为返回类型的 Variant

函数可以通过返回 variant 来返回几种类型中的一种。调用方随后检查它,以确定返回的是哪种类型。

#include <iostream>
#include <string>
#include <variant>
std::variant<int, std::string> parse(bool ok) {
    if (ok) return 42;
    return std::string("error");
}
int main() {
    auto r = parse(false);
    if (auto s = std::get_if<std::string>(&r)) std::cout << *s << "\n";
}

使用 emplace 就地更改

v.emplace<T>(args...) 会直接在 variant 内部构造一个类型为 T 的新值,并切换当前活动的备选类型。

#include <iostream>
#include <string>
#include <variant>
int main() {
    std::variant<int, std::string> v = 1;
    v.emplace<std::string>("switched");
    std::cout << std::get<std::string>(v) << "\n";
}

为何优先使用 Variant?

std::variant 兼具联合体的内存效率和完整的类型安全性:它会跟踪活动类型、管理生命周期,并拒绝错误类型的访问。下一课将展示处理它的最简洁方式。

快速检查

请检查您对 std::variant 的理解。

回顾

您学习了std::variant:

  • 保存几种类型中的一种,并跟踪当前保存的是哪一种。
  • 使用 holds_alternative / index() 检查活动类型。
  • std::get 在类型不匹配时抛出异常;get_if 返回指针或空值。
  • 安全地保存 std::string 等非平凡类型。

常见问题解答

「std::variant」课时是免费的吗?

是的 — 「std::variant」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C++ Academy 课程的其余内容,请升级到 CoddyKit PRO。 C++ Academy 课程共包含 4 节课。

「std::variant」这节课中我会学到什么?

类型安全的联合体 你通过在浏览器中直接运行的动手代码来练习 C++ Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C++ Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C++ Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「std::variant」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C++ Academy 课中编写并运行代码吗?

能。每节 C++ Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 带作用域的 enum class
  2. 联合体及其风险
  3. std::variant
  4. std::visit
← 返回 C++ Academy