如果我有一个唯一的指针,并且在函数中为其创建了一个别名,而该别名超出了范围,为什么原始的unique_ptr也不会被破坏?毕竟,在下面的函数中定义的“ b”与“ x”在内存中基本上是同一对象。幕后发生了什么?
#include <iostream>
#include <memory>
void testfunc(std::unique_ptr<int>& x) {
std::unique_ptr<int>& b = x;
}
int main() {
std::unique_ptr<int> a(new int(5));
std::cout << *a << std::endl; // 5
testfunc(a);
std::cout << *a << std::endl; // 5
}
答案 0 :(得分:2)
您正在使用的是一个引用,而C ++中的引用是与引用不同的类型。您可以通过引用与对象进行交互,但是引用本身和被引用的对象具有不同的生存期。当一个被销毁时,另一个不会自动销毁。这意味着您可以将引用传递给函数,然后在函数结束时销毁该引用,原始对象仍然有效。这允许绕过大型复杂对象,而无需复制甚至移动它们。这是一个实现细节,但对于编译器来说,通常只是使用“幕后”指针作为引用。
作为附带说明,C ++中的引用方面导致臭名昭著的悬而未决的引用问题。如果您持有对某个对象的引用,并且该对象被销毁,则该引用在技术上现在无效,并且如果使用它,您将调用未定义的行为。不幸的是,该语言没有内置任何东西可以自动检测或处理这种情况。您必须设计程序来避免它。
答案 1 :(得分:0)
#include <iostream>
#include <memory>
void testfunc(std::unique_ptr<int>& x) { // you take a reference to a unique_ptr
std::unique_ptr<int>& b = x; // which will do nothing to the lifetime of
} // the unique_ptr you pass to the function,
// then you assign the passed parameter
// to another reference. again, that does
// nothing to the lifetime of the original.
int main() {
std::unique_ptr<int> a(new int(5));
std::cout << *a << std::endl; // 5
testfunc(a);
std::cout << *a << std::endl; // 5
}
答案 2 :(得分:0)
毕竟,下面函数中定义的“ b”与“ x”在内存中基本上是同一对象。
一点也不。 x
是参考。引用不是对象,因此不会为其调用构造函数或析构函数。没有变量的“别名”。有用于类型的类型,也称为typedef。
用指针代替相同的代码:
void testfunc(std::unique_ptr<int>* x) {
std::unique_ptr<int>* b = x;
}
int main() {
std::unique_ptr<int> a(new int(5));
std::cout << *a << std::endl; // 5
testfunc(&a);
std::cout << *a << std::endl; // 5
}
引用唯一可以影响对象生命周期的时间是当引用绑定到临时对象时,但是即使这样,它也可以延长寿命而不是减少它:
struct A {};
int main() {
{
A(); // Constructed and destructed
}
{
A const& a = A(); // Constructed
// Other instructions
} // Destructed
}
答案 3 :(得分:0)
可以将reference视为元素的别名,因此它通过吸收其 value 并工作 just来引用就像它一样,但是它不会被销毁者调用或被程序员强行销毁,这也会销毁它引用的变量...,因为引用只是可编辑的别名 ...但是,它们的寿命有所不同,因为可以移动非引用类型,并且该类型变得超出范围 ... >
“ 幕后发生了什么?”
在内存中,引用使我们可以更改元素的值,并且如果经常使用来代替指针,而指针通常是C 中的常见做法。 strong>但是,除非通过,否则它的值不能移动。除非使用分配操作直接进行更改,否则引用的值将不会更改< / em>或间接 即,即功能参数 x
本身就是别名。 ..
就像:x = std::make_unique<int>(6);
会将a
的值改为6一样... 但是您在这里所做的却是...
auto& b = x;
除了x
(对a
的引用)所引用的值被复制并传递给{{1} }(它的作用类似于另一个别名)...因此,它类似于:b
,但是由于auto& b = a;
不在范围内,因此它引用了{{1} }的值间接 ...
a
因此,人们的普遍建议是,如果不确定其作用,则应避免引用(如果您不知道,可以更改 实际变量后果)...并花一些时间来learn about them ...
但是,如果您破坏了原始 ...,则所有引用本身都将失效...在这种情况下,当尝试访问< em>已销毁的(已无效)对象是未定义,导致undefined behavior ...