基本上我有两个相关的问题。让我们假设,有一个函数来创建一个共享指针,例如:std::shared_ptr<int> create_ptr(int val)
有一个函数通过引用接受,例如:void print(int& val)
我想创建一个共享指针,并将其直接传递给函数,如下所示:print(*create_ptr(123))
运算符 *()应该返回一个引用,但它将是对临时对象的引用。
你能告诉我,这样做是否仍然安全,并且根据C++规则是否完全正常?
我不确定,但我假设这是正常的,因为对象是分配的,直到函数完成才被删除。所以共享指针是临时的,但对象是真正分配的。
如果是这样的话,那么它可以解释为什么下面的代码编译得很好:
std::shared_ptr<int> create_ptr(int val)
{
return std::make_shared<int>(val);
}
void print(int& val)
{
std::cout << "*** Print value: " << val << '\n';
}
int main()
{
print(*create_ptr(123)); // Why does it work?
}
当我第一次写代码的时候,我预料到了一个编译错误,因为传递的对象是临时的,现在我仍然很困惑,为什么这应该工作?你怎么解释
谢谢你!
代码已经用GCC-10进行了测试,编译得很好,工作正常。
2条答案
按热度按时间uurv41yg1#
ptr的生存期将持续到整个表达式的求值,其中包括对
print
的调用。关于specs:
所有临时对象都被销毁,这是计算完整表达式的最后一步,该表达式(词法上)包含了它们被创建的点,如果创建了多个临时对象,则它们被销毁的顺序与创建顺序相反。即使该计算以引发异常而结束,也是如此。
fwzugrvs2#
我预计会出现编译错误,因为传递的对象是临时的,现在我仍然很困惑,为什么这样做会起作用?
它之所以编译是因为共享指针类的间接操作符重载不是左值ref限定的,所以在右值(如临时值)上调用它是有效的。
我假设,这是正常的,因为对象是分配的,而不是删除,直到函数完成。
你的假设是正确的。它没有解释为什么程序编译,但它解释了为什么行为定义良好。