[英]C++ variable scope for references
我很长时间以来第一次写一些C ++,记不清了。 我目前在范围方面(以及何时使用指针与引用作为输入参数的参考)最费劲。 具体来说,如果我在堆栈上创建某些内容,那么该内容将在其中保留多长时间?
如果我有一个简单的课程,例如:
class Person {
const std::string name_;
public:
Person(const std::string& name) : name_(name) {}
const std::string& get_name() { return name_; }
};
然后,我有一个简单的Person Generator方法和main:
Person* get_person() {
std::string name = "Bob";
return new Person(name);
}
int main (int argc, char **argv) {
Person* person = get_person();
// Is person's name Bob here? Or did Bob go out of scope?
delete person;
}
在删除人之前,该人的名字是否已经超出范围?
我知道我可以创建一个新的std :: string并将其传递给Person,但是我还有一个要清除的变量。 在方法签名中接受指针或引用的标准吗?
另外,也欢迎参考该主题的教程。
您在这里没有问题。 Person
的构造函数复制堆栈上的值。
让我们分解一下:
Person* get_person() {
std::string name = "Bob"; // 1)
return new Person(name); // 2)
} // 3)
字符串名称已创建
在这里,字符串name
是在堆栈上创建的。
在堆上创建一个新人
我们必须研究构造函数以了解发生了什么
class Person {
const std::string name_;
public:
Person(const std::string& name) : // 2.a)
name_(name) // 2.b)
{} // 2.c)
}
a) name
通过引用传递。 对name
的引用位于当前框架中,而name
在堆栈中位于前一框架中。
b) name
被复制到name_
。 因为此人是在堆上创建的,所以name_
在堆上。
c)对name
的引用被破坏了,因为它的范围结束了。
name
不在范围内。 我们返回一个指向name_
在堆上的Person
的指针,因此Person
(带有name_
)不会被销毁。 最重要的步骤是2.b)
。 这里,存在于堆栈中的名称被复制构造到堆中 。 这是因为name_
不是引用而是值,这使它与传入的name
“独立”。
Tl; dr人的名字不会超出范围,因为只有堆栈上的值才可以超出范围。 在这种情况下,只有指向人的指针位于堆栈上,而人及其名称将在堆上创建(通过new
),并且不会超出范围。
您的代码很好。
当您将对名称的引用传递给构造函数时,构造函数将从中创建一个新字符串,即name_将是name的副本并放置在堆中。
从get_person返回后,变量名超出范围,但已经进行了复制。
所以-没问题。
来自http://www.cplusplus.com/reference/string/string/string/
copy (2): string (const string& str);
(2) copy constructor Constructs a copy of str.
只要堆栈是相关的,分配在堆栈上的内容将一直保留在那里,并在弹出堆栈时立即销毁。
C ++倾向于采用两种方法从堆栈中获取数据:在堆上分配,使其比当前堆栈作用域的持久时间更长;以及复制。
您的name
变量是堆栈分配的std::string
但是由于您通过引用而不是指针传递它,因此将其复制到分配的C ++对象中。
内部字符串数据本身可以分配在堆上,这就是这些容器经常工作的方式,但这并不是您真正关心的问题。
简而言之,除非堆栈对象是堆分配的或在其他地方复制的,否则堆栈对象会在其作用域(例如函数或块)的持续时间内保持不变。
从风格上来看,您真正想要做的就是将所有有关Person
问题折叠到类中。 如果"Bob"
是默认名称,请创建一个构造器方法来分配该名称:
Person() : name_("Bob") { };
这避免了get_person()
混乱。
在您的代码中,“人”的名字会在那里出现。
方法签名通常接受引用,但是有时您希望通过副本传递。
这可能是方法签名的有用参考。 http://www.cplusplus.com/articles/z6vU7k9E/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.