你准备好加入 C 和 C++ 编程的宏伟世界了吗?你想在几行简单的 C++ 代码之后质疑自己的存在吗? 如果您的回答是“是的!”、 “是的” 或 “为什么不呢?” - 欢迎测试您的知识。您将被提出多个与 C 或 C++ 相关的问题。 请在故事结尾处找到正确的答案和解释。祝你好运! 1. 最小程序 main; 如果您尝试使用 C 编译器编译该程序,会发生什么? 无法编译 可以编译,但不能链接 将编译并链接 2. 叉子 #include <iostream> #include <unistd.h> int main() { for(auto i = 0; i < 1000; i++) std::cout << "Hello world!\n"; fork(); } 该程序将打印多少行? 1000 少于 1000 超过1000 3. 你所需要的只是指数 #include <iostream> int main() { int array[] = { 1, 2, 3 }; std::cout << (4, (1, 2)[array]) << std::endl; } 该程序将打印什么? 1 2 3 4 无法编译 不明确的 4.正则表达式 #include <regex> #include <iostream> int main() { std::regex re("(.*|.*)*O"); std::string str("0123456789"); std::cout << std::regex_match(str, re); return 0; } 这个正则表达式匹配这个输入字符串需要多长时间? 1 毫秒 1 秒 1 分钟 1 小时 1 年 永远 5. 移动和 lambda #include <iostream> struct Foo { Foo() { std::cout << "Foo()\n"; } Foo(Foo&&) { std::cout << "Foo(Foo&&)\n"; } Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; } }; int main() { Foo f; auto a = [f = std::move(f)]() { return std::move(f); }; Foo f2(a()); return 0; } 该程序打印的最后一行是... Foo() Foo(Foo&&) Foo(const Foo&) 6. X 和条形图 #include <iostream> int x = 0; int bar(int(x)); int main() { std::cout << bar; } 该程序将打印什么? 0 1 0x0 无法编译 不会链接 7. 构造函数 #include <iostream> struct Foo { Foo() { std::cout << "Foo()\n"; } Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; } Foo(int) { std::cout << "Foo(int)\n"; } Foo(int, int) { std::cout << "Foo(int, int)\n"; } Foo(const Foo&, int) { std::cout << "Foo(const Foo&, int)\n"; } Foo(int, const Foo&) { std::cout << "Foo(int, const Foo&)\n"; } }; void f(Foo) {} struct Bar { int i, j; Bar() { f(Foo(i, j)); f(Foo(i)); Foo(i, j); Foo(i); Foo(i, j); } }; int main() { Bar(); } 该程序打印的最后一行是... Foo(int, int) Foo(const Foo&, int) Foo(int, const Foo&) Foo(int) 而不是结论 我希望你永远不会在野外发现这种奇怪的片段。 答案 最小程序 这是合法的 C 代码。 如果您尝试运行它,它将崩溃。main - 是全局变量。 它将成功编译和链接。 main; 在 C 代码中,你可以省略很多东西。例如,你可以省略全局变量的类型。默认情况下,编译器会假定此类型为 。此外,C 中没有 (与 C++ 不同),因此在链接时无法区分变量 和函数 。 int 名称修改 main main 因此,编译器将编译有效的代码,并且链接器将在目标文件中找到名为 内容来链接程序。 main 分叉 这是 POSIX 特性,而不是 C 或 C++ 特性。IO 操作的实现使用缓冲区来优化性能。当您调用 时,操作系统将创建进程内存的写时复制副本,IO 缓冲区也可能会复制,缓冲字符串 。 fork 可能会被打印超过 1000 次 你所需要的只是指数 答案是 3 为了理解这段代码,让我们仔细看看 C 和 C++ 中的索引是如何工作的: 与 相同,与 相同,与 相同。 array[index] *(array + index) (index + array) index[array 第二条线索是运算符 。它是二元运算符,它丢弃左参数并返回右参数。 , 正则表达式 会发生什么!行为取决于实施。 无法预测 在我的环境中,这个程序引发异常 The complexity of an attempted match against a regular expression exceeded a pre-set level. 其他可能的选择是时间出奇地长或按预期工作。这是因为有两种可能的方法来实现正则表达式。 首先 - 将正则表达式转换为有限自动机 (n - 模式长度),匹配字符串 (m - 字符串长度)。此方法不支持 O(n**2) O(m) 回溯。 第二种 - 贪婪方法 + DFS,支持回溯但在某些模式下容易出现指数时间复杂度。 移动和 lambda 答案是 。默认情况下,Lambda 是不可变的,使用 捕获到 lambda 中的所有值都隐式为 。这解锁了 lambda 的 行为。 Foo(const Foo&) [] const 幂等 当你移动 时,你创建了 。 是一种奇怪的类型,因此编译器只复制 f const Foo&& const Foo&& Foo 有两种方法可以解决此问题: 创建可变的 lambda auto a = [f = std::move(f)]() mutable { return std::move(f); }; 声明构造函数 Foo(const Foo&&) X 和条形图 。 该程序将打印 1 — 是一种声明函数的奇怪方式,它等于 。 int bar(int(x)); int bar(int x); 如果您与类型转换感到困惑, - 这是类型转换。 int bar((int(x))); 然后我们尝试将函数地址隐式转换为 ,这种转换的结果始终为 。 bool true 函数 从未被使用过,这使得我们在链接时避免未引用的符号错误。 bar() 构造函数 最后一行是 。 Foo(const Foo&, int) 是变量声明,与 相同。因此名称为 的类成员在此范围内是隐藏的。 Foo(i) Foo i i