你真的懂 C++ 吗?来看看这 5 个问题吧!
移动语义
问题
以下的代码打印的结果是什么?
#include <iostream>
#include <utility>
struct example
{
example() = default;
~example() = default;
example(const example &) = default;
example(example &&)
{
std::cout << "move constructor invoked\n";
}
int data{0};
};
int main()
{
example e;
e.data = 5;
example new_e{std::move(e)};
std::cout << e.data << '\n' << new_e.data;
}
答案
move constructor invoked
5
0
解释
std::move 仅仅是将 \(1\) 个左值表达式通过 static_cast<T&&> 转换到 \(1\) 个右值表达式,而右值构造函数仅仅是调用语义上的移动构造函数,并不代表实际一定产生移动操作,具体的移动操作由移动构造函数内对应的实现来实现,被移动后的对象处于 valid but unspecified 的状态
参考
https://en.cppreference.com/w/cpp/utility/move.html
Lambda表达式
问题
以下 \(2\) 段代码是否都能够正常编译?如果能正常编译,输出的结果分别是什么?
样例 1
#include <iostream>
int main()
{
int x{1}, y{2};
auto f = [x, y]() {
x = y;
++y;
};
std::cout << x << ' ' << y;
}
样例 2
#include <iostream>
int main()
{
int x{1}, y{2};
auto f = [&x, &y]() {
x = y;
++y;
};
f(x);
std::cout << x << ' ' << y;
}
答案
样例 1
无法编译,必须追加 mutable 关键字,如下:
#include <iostream>
int main()
{
int x{1}, y{2};
auto f = [x, y]() mutable {
x = y;
++y;
};
f(x);
std::cout << x << ' ' << y;
}
打印的结果为:
1 2
样例 2
可以编译,打印的结果为:
2 3
解释
lambda 表达式其实是通过声明 \(1\) 个非联合非聚合匿名类来实现的,在这个类中,会按照捕获列表声明类内的私有成员,其默认生成的 operator() 函数被声明为 const ,除非你使用了 mutable 进行修饰
参考
https://en.cppreference.com/w/cpp/language/lambda.html
大括号初始化与列表初始化
问题
在C++ 14及以上标准中,以下的 a 、b 分别被推导为什么类型?
int main()
{
auto a{1};
auto b = {1};
}
答案
int 、std::initializer_list<int>
参考
https://en.cppreference.com/w/cpp/language/auto.html
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3922.html
string_view
问题
以下代码是否会引发 UB ,为什么?
#include <iostream>
#include <string_view>
std::string_view get()
{
std::string s{"Hello"};
return s;
}
int main()
{
std::cout << get();
}
答案
会
解释
std::string_view 返回 \(1\) 个字符串视图,其自身不持有字符串的所有权,如果视图返回了 \(1\) 个已经没有作用域的对象,就会引发未定义行为
具体的原因是 std::string 析构后,内部的 char* 失效,而 string_view 不拥有其指向的内存
结构化绑定
以下 \(2\) 段代码打印的结果分别是什么?
样例 1
#include <iostream>
#include <utility>
using point = std::pair<int, int>;
int main()
{
point p{1, 2};
auto [x, y] = p;
std::cout << std::boolalpha << (&x == &p.first) << '\n';
std::cout << std::boolalpha << (&y == &p.second);
}
样例 2
#include <iostream>
#include <utility>
using point = std::pair<int, int>;
int main()
{
point p{1, 2};
auto &[x, y] = p;
std::cout << std::boolalpha << (&x == &p.first) << '\n';
std::cout << std::boolalpha << (&y == &p.second);
}
答案
样例 1
false
false
样例 2
true
true
解析
结构化绑定实际上就是声明了新的变量,如果是拷贝,那么自然不会共享地址,但如果是引用,那么地址自然一样
参考
https://en.cppreference.com/w/cpp/language/structured_binding.html

浙公网安备 33010602011771号