【发布时间】:2019-07-12 15:14:10
【问题描述】:
我目前正在开发一个特定的嵌入式系统(使用 C++),其中没有太多内存。因此,使用 new/delete 是不可能的。我确实设置了一些内存管理系统,但是,我正在探索一些其他方法来解决某些问题(与内存管理不完全相关,但这在这里并不重要)。搜索时,弹出了一个相当简单的问题,但我仍然不能 100% 确定答案,所以我想听听专家的意见。
我最后的问题实际上是关于 C++ 中的引用,以及瞬态对象的功能。
class Obj
{
// id is automatically set, starting from 1, step by 1
public: const int id = ...;
// other unrelated stuff in the class
};
class Test
{
public: Obj& obj;
public: Test(Obj&& o) : obj(o) { }
};
void test()
{
Obj o1; // id is 1
Obj o2; // id is 2
Test t = Obj(); // [*] id of this transient obj is 3
cout << t.obj.id << endl; // prints 3, as expected?
}
我知道右值引用是左值(因为它们是命名对象,而命名对象总是左值),因此 Test 类没问题并且没有错误(编译错误)。但是,据我所知,瞬态对象 Obj()(标有 *)应该在 ; 之后被销毁。在同一行,所以如果我是正确的,那么之后的测试对象“t”应该对被破坏的对象有一个无效的引用。并且 3 打印实际上是出乎意料的行为,但意外的是它仍然有 3 写入它的内存位置,我在打印它时正在访问它。这是实际发生的事情,还是我缺乏看到/知道的其他事情?是否有某种机制来检测这种情况并延长/延长对象的生命周期,直到引用它的对象也被销毁(在本例中,延长 Obj() 的生命周期直到函数测试结束( ),当 't' 被破坏时)?
【问题讨论】:
-
这是实际发生的情况吗,[...]? 是的。你只是“幸运”它成功了。
-
为什么将右值引用作为构造函数参数?在这种情况下,普通的绝对没问题。
-
@Aconcagua 我总是用外部的右值调用构造函数。我知道这看起来很傻,是的,我可以用 new 完成所有这些操作,并使用指针而不是引用,但我不能使用 new(我试图尽可能避免它,所以我正在寻找其他一些解决方案)。
-
@Vlladz 我不是在谈论指针,而是在谈论引用。
Test(Obj& o) : obj(o) { }也会做同样的事情——甚至早在 r 值引用之前就已经存在了…… -
@Aconcagua 在这种情况下,我不能传递右值,只能传递左值,而且我总是将右值传递给构造函数。例如。如果我切换到您的解决方案,我将无法传递我真正需要的 Obj()。