关于右值引用作为类成员的C++技术疑问
C++右值引用结构体相关问题
代码示例
#include <iostream> template<typename T> struct test { T &&val; }; long double get() { return 6; } long double &get_ref() { static long double a = 5; return a; } int main() { test<long double> t_by_value{get()}; // 我认为这是容器 test<long double&> t_by_ref{get_ref()}; // 我认为这是视图 std::cout << t_by_value.val << " " << t_by_ref.val << "\n"; // 输出:6 5 std::cout << sizeof(t_by_value) << " " << sizeof(t_by_ref) << "\n"; // 32位系统下输出:4 4 }
问题
- 上述代码是否正确,是否存在未定义行为?
- 若代码正确,
test<long double>中的long double存储在哪里,因为它并未包含在对象中? - 我将
test<long double>称为容器、test<long double&>称为视图的说法是否正确?
回答
代码正确,不存在未定义行为。
test<long double>中的val是右值引用,当它绑定到get()返回的临时long double对象时,C++标准明确规定:绑定到右值引用的临时对象,其生命周期会被延长至该引用的生命周期结束,也就是t_by_value对象销毁时。因此访问t_by_value.val是完全安全的。test<long double>的结构体内部只存储了右值引用(大小等同于指针),真正的long double临时对象被存储在栈内存中(或编译器优化后的其他内存区域),并没有嵌入到test结构体对象里。临时对象的生命周期被右值引用延长,只要t_by_value存在,这个临时对象就不会被销毁。该说法并不准确:
test<long double>不能称为容器。容器的核心特性是管理数据的存储与生命周期,而这个结构体只是持有一个右值引用,没有真正“容纳”long double对象,临时对象的生命周期是靠C++标准规则被动延长的,并非结构体主动管理。test<long double&>可以勉强看作一种极简视图,因为它持有对已存在对象的引用,本身不拥有数据,仅提供访问途径,符合视图“不持有数据、仅引用数据”的基本特征,但它是非常简陋的实现,和标准库中的视图(如std::span)的功能不可同日而语。
内容的提问来源于stack exchange,提问作者Chameleon
相关产品推荐
相关产品推荐

