【问题标题】:c++ pointer scopec++ 指针作用域
【发布时间】:2011-06-01 23:54:39
【问题描述】:

当你有以下代码时会发生什么:

void makeItHappen()
{
    char* text = "Hello, world";
}

text 是否超出范围并被自动删除,还是留在内存中?

那么下面的例子呢:

class SomeClass
{
    public:
      SomeClass();
      ~SomeClass();
};

SomeClass::SomeClass() { }
SomeClass::~SomeClass()
{
    std::cout << "Destroyed?" << std::endl;
}

int main()
{
    SomeClass* someClass = new SomeClass();
    return 0;
} // What happend to someClass?

这里会发生同样的事情吗?

谢谢!

【问题讨论】:

    标签: c++ pointers scope


    【解决方案1】:

    变量 text 确实超出了范围(但是字符串文字没有被删除)。

    对于您使用 new 分配的对象(例如您的 SomeClass),您需要显式删除它们。如果您希望自动删除像这样分配的对象,请查看boost smart pointers(如果您的编译器支持 c++0x,则为 std::unique_ptr)。

    这将在共享指针超出范围时自动删除分配的对象。

    您的代码将如下所示:

    int main(int argv, char **argv)
    {
      boost::scoped_ptr<SomeClass> ptr(new SomeClass);
      // the object is automatically deleted
      return 0;
    }
    

    注意:在这个特定示例中,您还可以使用 std::auto_ptr(但在 c++0x 中将不推荐使用)。

    注 2:正如 Kos 在 cmets 中所指出的,在这种情况下使用 boost::scoped_ptr 或 std::unique_ptr (c++0x) 更合适。我的回答首先使用了 boost::shared_ptr,例如,如果您需要在多个类之间共享指针的所有权,这更合适。

    【讨论】:

    • 我想 +1... 但后来我注意到你提到了引用计数指针,当更合适的工具是来自 c++0x / boost::scoped_ptr / @987654325 的 std::unique_ptr @。当指针超出范围时,它们负责删除对象 - 并且正是为此。
    • @Kos:你是绝对正确的,在这种特殊情况下 unique_ptr 更合适。我会做出改变...
    • +1 然后。 :) (最后一个 shared_ptr 链接是故意留下的吗?)
    • 啊,你的眼光不错... :) 我将链接文本更改为更准确。也许我可以聘请您作为代表来校对我所有的答案...谢谢!
    【解决方案2】:

    在第一个示例中,字符串文字存储在可执行文件的数据段中。
    在第二种情况下,您不必调用delete(在您的示例程序中只是终止),因为在程序终止时,无论如何都会为进程释放堆。
    请注意,即使程序终止,您也必须显式释放堆(正如我所读),因为它不会在终止时为您清理。
    当然,程序员负责 C++ 中的内存管理,并且您在堆上创建的对象一旦不需要就应该是deleteed。

    【讨论】:

      【解决方案3】:

      text 是否超出范围

      是的!它是函数makeItHappen() 的本地函数,当函数返回时,它会超出范围。但是,指向的字符串文字 "Hello, world"; 具有静态存储持续时间,并且存储在内存的只读部分中。

      那么下面的例子呢:

      ......
      同样的事情发生在这里吗?

      您的第二个代码示例泄漏了内存。

      SomeClass* someClass = new SomeClass();

      someClassmain() 的本地变量,因此当 main 返回时,它作为自动变量被销毁。但是,指向的对象仍保留在内存中,并且在函数返回后无法释放它。您需要显式写入delete someClass 才能正确释放内存。

      【讨论】:

      • +1 "指向的字符串字面量 "Hello, world";具有静态存储持续时间"
      • 内存泄漏,因为您没有删除您创建的对象。
      【解决方案4】:
       char* text = "Hello, world";
      

      这里在堆栈上创建了一个自动变量(指针),并设置为指向常量内存中的一个值,这意味着:

      • "" 中的字符串字面量存在于整个程序执行过程中。
      • 您不负责“分配”或“释放”它
      • 您不能更改它。如果要更改它,则必须分配一些“非常量内存”并将其复制到那里。

      当指针超出范围时,内存指针本身(4字节)被释放,字符串仍然在同一个地方——常量内存。

      对于后者:

      SomeClass* someClass = new SomeClass();
      

      然后someClass 指针在超出范围时也会被释放(因为指针本身也在堆栈上,就在第一个示例中)... 但不是对象!

      关键字new 基本上意味着您为free store 上的对象分配了一些内存——并且您有责任在某个时候调用delete 以释放该内存。

      【讨论】:

      • @Kos:这是否意味着int x = 2;中的数字2也存在于整个程序执行过程中?
      • 不同之处在于数字 2 不需要在内存中有地址,而字符串有(因为它被指针指向)。 (这个数字 2 存在于内存的代码部分中,您不需要直接访问它,因为它是代码,而不是数据。)
      • @Kos 感谢您的精彩回答!但是,在内存中保留"Hello, world" 有什么意义?
      • 您需要将它保存在某处,对吗? :) 它需要在内存中,以便您能够将其地址传递给printf 函数。
      • @Kevin,你的程序的整个代码(编译后的二进制代码)在程序执行期间都留在内存中,这里的常量字符串字面量也遵循同样的规则。
      猜你喜欢
      • 1970-01-01
      • 2020-12-09
      • 1970-01-01
      • 2011-05-02
      • 2011-06-04
      • 1970-01-01
      • 1970-01-01
      • 2014-06-26
      • 1970-01-01
      相关资源
      最近更新 更多