在C++(我使用QT)中,我可以通过以下两种方式创建QString类的实例:
方法1
QString str = "my string";
方法二
QString *str = new QString("my string");
我知道这与指针有关。所以我的问题是:
- 这两者之间的区别是什么?
- 我应该坚持使用哪种方法?
- 何时正确地使用方法1,何时正确地使用方法2?
- 在方法2中,我可以通过调用
delete str;
来销毁对象。使用方法1时如何删除str
变量?
在C++(我使用QT)中,我可以通过以下两种方式创建QString类的实例:
QString str = "my string";
QString *str = new QString("my string");
delete str;
来销毁对象。使用方法1时如何删除 str
变量?两种方法主要的不同在于它们的生命周期:在第二种方法中创建的对象将一直存在,知道调用 delete 方法;而在第一种方法中,它将在函数调用后自动销毁(如果有)。此外,由于涉及到非平凡的内存管理,第二种方法需要更多的工作。
使用符合你所需生命周期的方法。如果第一种方法的寿命已经足够,请不要使用第二种方法,因为它会增加内存管理的开销。如果你可以重构程序并同时改进设计,那将更加高效和优雅。
请参考上面的第二条。尤其是,使用第一种方法并存储指向该对象的指针并在其生命周期结束后访问它,是一个陷阱。虽然使用第二种方法也可能出现这种情况,但显式的销毁使程序员更加注意它(但仍然因为生命周期不明确,这是一个常见的陷阱)。第二种方法的陷阱是忘记删除它,导致内存泄漏(或过早地删除它并像前面一段描述的一样引用它)。
在第一种方法中,当函数返回时,对象将被自动删除。
p
的生命周期将在该语句结束时结束(对象将在语句结束时被销毁)。QString q = f()
与QString q(f());
相同,因此会构造一个临时对象并传递给QString
的复制构造函数,然后在语句结束时销毁该临时对象。但是,编译器可以自由地优化掉它。 - Seth CarnegieQString str("my string");
创建一个对象,其生命周期是自动管理的:如果它是局部变量,则该对象存在于其封闭作用域的结尾,如果它是全局变量,则该对象存在于程序的结尾。
new QString("my string");
创建一个具有手动管理生命周期的对象,也称为“动态对象”(并返回指向该对象的指针)。这意味着您负责管理对象的生命周期。这几乎从不是正确的做法,除非您正在编写库组件。unique_ptr<T>
或shared_ptr<T>
处理程序类来处理它们。new
,永远不要使用delete
。
(进一步的提示:1)除非用于ADL,否则永远不要使用using namespace
。2)除非您正在编写库组件,否则设计良好的类不应具有析构函数、复制构造函数或赋值运算符。如果有这些内容,请将有问题的逻辑因素提取到单一责任库组件中,然后查看2)。)
new
调用,这些调用没有与删除配对。我更喜欢addWidget采用QSharedPointer,但是... https://dev59.com/0HI-5IYBdhLWcg3w1sPi.html - HostileFork says dont trust SEunique_ptr
,它是否可以得到改善……希望最终会有一个C++11版本的Qt来进行一些清理。另外请注意,问题及我的回答都是关于“C++中的对象”,而不是关于“Qt最佳实践”的。 - Kerrek SBstr
、类型为QString
且初始值为"my string"
的对象。str
的QString
类型指针。方法一采用自动内存管理(对象在超出范围时将被删除)。
方法二是手动内存管理 - 直到调用delete str;
才会被删除。
如果您忘记删除它 - 这会创建我们所谓的内存泄漏!
通常,除非您有使用指针的原因(减少错误的机会),否则方法一将是最佳选择。
您可能会发现这很有帮助: 为什么要使用指针?
什么时候使用方法1,什么时候使用方法2是正确的?
在这个例子中,当你可以使用指针并不明显。但是如果你创建自己的类,例如Images,它保存了大量的数据,并且你想要在函数或方法中传递该类的对象,那么我建议你使用指向对象的指针而不是对象本身。为什么?如果你传递一个指向函数的指针,你只传递了对象的内存地址(你复制了几个字节),但是如果你传递对象本身,那么你传递了大量的数据,这可能会减慢你的应用程序。
让我们看另一个例子:假设你有一个带有三个参数的函数,函数体应该在函数结束时更改每个参数。正如你所知,函数只能返回一个值,因此你可以在函数体中使用指针来更改每个参数。
使用指针有很多原因,你在使用它们时应该小心。我建议你阅读一些关于这个主题的文章。
我希望你理解了区别。关键概念是对象地址和对象本身之间的区别!
QString str("my string");
。忘记指针,new
和delete
的所有内容。大多数情况下,它们都不是正确的工具。 - Kerrek SB