【问题标题】:C++ pointer function and new keywordC++指针函数和new关键字
【发布时间】:2022-01-05 12:50:57
【问题描述】:

美好的一天,

当我尝试学习一门编程语言时,我通常发现最好查看其他人的代码。

我现在正在尝试学习 C++,但在理解以下函数时遇到了一些困难(例如):

Vehicle* MyClass::GetVehicleByID(uint id)
{
    Vehicle* car = new Vehicle;
    car->model = vehiclesArray[id].model;
    return car;
}

int main()
{
    Vehicle* car = myClass.GetVehicleID(0);
    std::cout << "Car Model: " << car->model << std::endl;
}

我想我理解指针的概念。但我不明白这个对象什么时候会被销毁。我是否必须在主函数中手动删除对象“汽车”?另外,为什么我们使用 new 关键字而不是仅仅使用“Vehicle car();”?据我了解,新关键字将在使用对象填充之前分配内存?

只是问这些问题,我是否完全超出了我的理解范围?我在哪里或如何学习了解这段代码中发生了什么?因为似乎所有教程都只解释“基础”,例如指针是什么以及最基本的使用方法。

任何帮助将不胜感激。

【问题讨论】:

标签: c++11


【解决方案1】:

是的,如果您使用new 关键字创建对象,则必须使用delete 关键字将其删除。 C++ 中没有垃圾收集。所以在你的情况下,这将是:

delete car;

此外,使用new 创建与您建议的直接使用构造函数之间的区别在于,使用 new 时,对象是在堆上创建的,并且它的生命周期会延长,直到它被程序员明确删除。在另一种情况下,它将在堆栈上创建,并在退出封闭函数或块时自动删除。

在您的情况下发生的是您在堆上创建一个对象并且从不删除它。这会导致所谓的内存泄漏。由于您的程序很小,因此这不是问题,并且在程序完成后会释放此内存。但是,在长时间运行的程序或经常在堆上分配的程序的情况下,可能会导致程序耗尽可用内存。

还请注意,您可以在函数内创建一个对象,更改签名以返回一个对象而不是指针,并让函数直接返回该对象。这会起作用,但首先会在堆栈上创建函数本地的对象。然后该对象将被复制到在主函数中创建的另一个对象中,然后将删除第一个对象。这不是很有效,这就是为什么使用指向在堆上分配的对象的指针的原因。更多使用堆的原因之一是用于存储大型对象。栈比堆小,不应该用来存储非常大的对象。

我希望这能澄清一点,但要理解这一切需要大量的时间和工作,在 stackoverflow 上的答案是不够的。我建议阅读更多关于 C++ 中堆上的对象和堆栈上的对象之间的差异。网上资料很丰富。

【讨论】:

  • 如果 OP 按值返回,则局部变量将被移动,而不是复制(或完全优化,由于 NRVO)。无论如何,我希望它比堆分配更快。
  • 感谢您的解释。你帮助我更好地理解了正在发生的事情。我一定会阅读有关堆栈和堆的信息。
  • @HolyBlackCat 移动不会在所有情况下都发生,它取决于类的实现,而且它通常仍然比复制指针更昂贵。如果我没记错的话,从 c++17 开始保证 NRVO,许多项目仍然不使用。我正在尝试向 OP 解释非常基础的知识,以便他可以更好地掌握事物。这显然是他所需要的,因为他对 C++ 还很陌生。您不能指望我在一个 SO 答案中涵盖所有细节和每种特殊情况。一个人需要一本书的一章,甚至几章。
  • 我不是在争论整个答案的优点,只是其中一个句子的措辞。 NRVO 从不保证,C++17 只保证 RVO。
【解决方案2】:

仅针对您的代码问题。 也许使用shared_ptr而不是指针会更好

#include <memory>

std::shared_ptr<Vehicle> MyClass::GetVehicleByID(uint id)
{
    std::shared_ptr<Vehicle> car = std::make_shared<Vehicle>();
    car->model = vehiclesArray[id].model;
    return car;
}

int main()
{
    std::shared_ptr<Vehicle> car = myClass.GetVehicleID(0);
    std::cout << "Car Model: " << car->model << std::endl;
}

shared_ptr 类基于RAII 准则。因此,您可能不必删除它。当main()结束时,会调用析构函数shared_ptr::~shared_ptr(),并删除指针。

无论如何,阅读

是个好主意

【讨论】:

  • 这个问题更多是关于了解后台实际发生的事情以及事情的工作原理。虽然使用智能指针通常是一个很好的建议,但建议在这里使用它只会增加混乱并产生更多问题。
猜你喜欢
  • 1970-01-01
  • 2012-03-06
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
  • 2010-12-28
  • 2021-06-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多