在C ++中(我使用QT)我可以用两种方式创建QString类的实例:
QString str = "my string";
QString *str = new QString("my string");
我知道这与指针有关。所以我的问题是:
delete str;
来销毁对象。如何在使用方法1时删除str
变量?由于
答案 0 :(得分:5)
主要是他们有不同的生命周期:方法2中创建的对象任意长,直到你调用delete;在方法1中,它将在堆栈上创建,并在从函数调用返回时被销毁(如果有的话)。其次,方法2需要更多的工作,因为非平凡的内存管理。
使用匹配您想要的生命周期的方法。如果方法1的生命周期足够好,则不要使用方法2,因为它需要内存管理的开销。如果您可以重构您的程序,以便您可以使用方法1同时改进设计,那将更加高效和优雅。
见上文2.特别是,使用方法1并存储指向对象的指针并在其生命周期之后访问它是一个陷阱。这也可以通过方法2实现,但显式破坏会将程序员的注意力集中在它上面(但仍然因为生命周期并不简单,这可能是一个陷阱)方法2的一个缺陷是忘记删除它导致内存泄漏(或删除它)太早,并且如本段前面所述那样引用它
在方法1中,当函数返回时,对象将被自动删除。
答案 1 :(得分:5)
两者是非常不同的东西。
QString str("my string");
创建一个对象,其生命周期自动管理:对象要么生活在其封闭范围的末尾(如果它是局部变量),要么生命周期结束程序(如果它是一个全局变量)。
new QString("my string");
使用手动管理的生命周期创建一个对象,也称为“动态对象”(并返回指向此对象的指针)。这意味着你负责管理对象的生命周期。除非您正在编写库组件,否则这几乎永远不是正确的事情。
这就是C ++哲学的核心:C ++是一种用于库编写的语言。您可以使用工具编写高质量,可重复使用的组件。如果您这样做,您将需要了解终身管理的复杂性。但是,直到这段时间,您应该使用现有的库组件。这样做时,您会发现几乎不需要执行任何手动管理。
使用动态容器(向量,字符串,映射等)来存储数据并构建自己的数据结构。如果需要修改调用者范围内的对象,则通过引用传递参数。从更简单的组件构建复杂的类。如果您确实必须拥有动态对象,请通过unique_ptr<T>
或shared_ptr<T>
处理程序类来处理它们。
不要使用指针。很少使用new
和delete
从不。
(进一步提示:1)除非是ADL,否则切勿使用using namespace
。 2)除非你正在编写库组件,否则精心设计的类不应该有析构函数,复制构造函数或赋值运算符。如果他们这样做,将违规逻辑分解为单一责任库组件,然后参见2)。)
答案 2 :(得分:3)
使用第一种语法时,您将创建名称为str
且对象类型为QString
且初始值为"my string"
的对象。
在第二个声明中,您创建名为QString
的{{1}}类型的指针。
指针不保持值,它们指向存储值的存储位置,差异很大。
答案 3 :(得分:2)
方法一将使用自动内存管理(当对象超出范围时将删除该对象)。
方法二用于手动内存管理 - 在调用delete str;
之前不会删除它
如果您忘记删除它 - 这会产生我们称之为内存泄漏的行为!
通常方法一是最好的选择,除非你有理由使用指针。 (错误的机会减少)
您可能会发现这有用: Why use pointers?
答案 4 :(得分:2)
不同之处在于方法一在堆栈上创建QString
,第二种方式在免费商店中创建QString
。 (请注意,QString s = "hello";
与QString s("hello");
完全相同。)就像parapura rajkumar所说,当你可以时总是做1,而当你做不到1时总是做。
方法1有许多优点,其中最重要的是自动内存管理。当QString
超出范围时,delete
占用的内存将自动释放,因此您无需执行任何操作来释放其内存。方法2要求您在完成释放内存时使用new
,否则您将发生内存泄漏。
另一个优点是,在堆栈上创建内容比在免费商店中创建更快 。
必须使用方法2的情况是,当您需要该对象的持续时间超过您所使用的范围时。然后您将使用{{1}在免费商店中分配这样它会持续到你在它上面调用delete
,然后传递指针。
答案 5 :(得分:1)
何时使用方法1是正确的,何时使用方法2是正确的?
在此示例中,何时可以使用指针并不明显。但是如果您创建自己的类,例如包含大量数据的Images,并且您希望在函数或方法中使用该类的传递对象,那么我建议您使用指向对象的指针而不是对象本身。为什么?如果你传递一个指向函数的指针,你只传递对象的内存地址(你正在复制几个字节),但是如果你传递对象本身,那么你传递的是大量数据,这会减慢你的应用程序。
让我们看另一个例子: 假设你有一个带有三个参数的函数,函数体应该在函数结束时改变每个参数。如您所知,函数只能返回一个值,因此可以更改函数体中每个参数的一种方法是使用指针。
使用指针有很多原因,使用它们时应该小心。我建议你阅读一些关于这个主题的文章。
我希望你能理解其中的差异。关键概念是对象地址和对象本身之间的区别!