引用的 C++ 变量范围

标签 c++ scope

我很长时间以来第一次写一些 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* get_person() {
    std::string name = "Bob"; // 1)
    return new Person(name); // 2)
} // 3)
  1. 字符串名称创建

    此处在堆栈上创建了字符串 name

  2. 在堆上创建一个新的人

    我们必须查看构造函数以了解发生了什么

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 的引用被销毁,因为它的作用域结束了。

  1. block 结束,因此 name 超出范围。我们返回一个指向堆上的 Person 的指针,因此 Person - 及其 name_ - 不会被销毁。

最重要的一步是2.b)。在这里,堆栈 中的名称被复制构造到 中。这是因为 name_ 不是引用而是一个值,这使得它“独立”于传入的 name


Tl;dr 这个人的名字不会超出范围,因为只有堆栈上的值才能超出范围。在这种情况下,只有一个指向人的指针位于堆栈中,而人及其名称是在堆上创建的(通过 new)并且不会超出范围。

关于引用的 C++ 变量范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31345509/

相关文章:

JavaScript 函数中函数的作用域

c++ - 指向单例的共享指针不能相互识别

c++ - 解包 std::array

c++ - qt - QNetworkConfigurationManager::configurationAdded 信号不工作

Perl:哈希片不能按词法作用域

javascript - Kyle Simpson 的 YDKJS 中的动态范围和 `this`

c++ - 在最佳时间从 _variant_t 获取 char*

c++ - 在 Windows 上为 c++ 使用 cmake

c# - Ninject - 如何在范围内保存常量?

ruby-on-rails - 基于 has_many 范围计数的 Rails 事件记录范围