这是c++中实例化对象的正确方法

Which is the right way to instantiate objects in C++?

本文关键字:方法 对象 c++ 实例化 这是      更新时间:2023-10-16

在c++中(我使用QT),我可以用两种方式创建QString类的实例:

方法1

QString str = "my string";

方法2

QString *str = new QString("my string");

我知道这与指针有关。所以我的问题是:

  1. 两者的区别是什么?
  2. 我应该坚持哪种方法?
  3. 何时使用方法1是正确的,何时使用方法2是正确的?
  4. 方法2中,我可以通过调用delete str;来销毁对象。使用方法1时,如何删除str变量?

谢谢

  1. 主要是它们有不同的生命周期:在方法2中创建的对象将会任意长时间地存在,直到你调用delete;在方法1中,它将在堆栈上创建,并在函数调用(如果有的话)返回时销毁。次要方法2需要更多的工作,因为非琐碎的内存管理。

  2. 使用与所需生存期匹配的方法。如果方法1的生命周期足够好,就不要使用方法2,因为它会带来内存管理的开销。

  3. 如果你可以重构你的程序,这样你就可以使用方法1,同时也可以改进设计,这将更有效和优雅。
  4. 见2。以上。特别是,使用方法1并存储指向对象的指针并在其生命周期后访问它是一个陷阱。这对于方法2也是可能的,但是显式的销毁将程序员的注意力集中在它上(但仍然因为生命周期不是直接的,这是一个可能的陷阱)方法2的陷阱是忘记删除它导致内存泄漏(或删除它太早,并引用它如本段前面所述)

  5. 方法1中的对象将在函数返回时被自动删除。

这两者是完全不同的。

QString str("my string");创建了一个生存期为自动管理的对象:该对象要么活到它的封闭作用域结束(如果它是一个局部变量),要么活到程序结束(如果它是一个全局变量)。

new QString("my string");创建一个具有手动管理生存期的对象,也称为"动态对象"(并返回指向该对象的指针)。这意味着负责管理对象的生命周期。从来都不是正确的做法,除非你正在编写一个库组件。

这就是c++哲学的核心:c++是编写库的语言。您拥有编写高质量、可重用组件的工具。当您这样做时,您将需要了解生命周期管理的复杂性。然而,在出现之前,您应该使用现有的库组件。当这样做时,您将发现几乎不需要执行任何手动管理。

使用动态容器(向量,字符串,映射等)来存储数据并构建自己的数据结构。如果需要修改调用者作用域中的对象,则通过引用传递参数。从简单的组件构建复杂的类。如果你真的必须有动态对象,通过unique_ptr<T>shared_ptr<T>处理程序类来处理它们。

不要使用指针。很少使用new,从不使用delete

(进一步提示:1)永远不要使用using namespace,除非它用于ADL。2)除非你正在编写库组件,否则设计良好的类不应该有析构函数、复制构造函数或赋值操作符。如果它们确实存在,则将违规逻辑分解为单一责任库组件,然后参见2)。

当您使用第一种语法时,您正在创建名称为str的对象,其类型为QString,初始值为"my string"

在第二个声明中,您创建了类型为QString的指针,其名称为str

指针不保存值,它们指向存储值的内存位置,两者的区别很大。

方法一将使用自动内存管理(当对象超出作用域时将被删除)。

方法二用于手动内存管理——在调用delete str;之前它不会被删除如果您忘记删除它——这就造成了我们所说的内存泄漏!

通常方法一是最好的选择,除非你有理由使用指针。(减少出错的机会)

你可能会发现这很有用:为什么要使用指针?

区别在于方法一在堆栈上创建QString,而方法二在自由存储上创建QString。(注意,QString s = "hello";QString s("hello");完全相同。)就像parapura rajkumar说的,当你能做的时候总是做1,当你不能做1的时候总是做2。

方法1有很多优点,其中最重要的是自动内存管理。该QString占用的内存将在超出作用域时自动释放,因此您不需要做任何事情来释放其内存。方法2要求您在使用完delete后使用它来释放内存,否则将发生内存泄漏。

另一个优点是,在堆栈上创建东西比在自由存储上创建东西快得多。

必须使用方法2的情况是当您需要该对象比您所在的作用域持续更长时间时。然后使用new在自由存储中分配,这样它就会持续到调用delete,然后传递指针。

何时使用方法1正确,何时使用方法2正确?

在本例中,何时可以使用指针并不明显。但是如果你创建自己的类,例如Images,它保存了很多数据,你想在函数或方法中传递那个类的对象,那么我建议你使用指向对象的指针,而不是对象本身。为什么?如果你传递一个指针到一个函数,你只传递了对象的内存地址(你复制了几个字节),但是如果你传递的是对象本身,那么你传递了大量的数据,这可能会减慢你的应用程序。

让我们看另一个例子:假设你有一个有三个参数的函数,函数体应该在函数结束时改变每个参数。如您所知,函数只能返回一个值,因此可以改变函数体中每个参数的一种方法是使用指针。

使用指针的原因有很多,在使用指针时应该小心。我建议你读一些关于这个主题的文章。

我希望你能理解其中的区别。关键概念是对象地址和对象本身的区别!