使用指针的优点/缺点

Advanages/Disadvantages of using pointer

本文关键字:缺点 指针      更新时间:2023-10-16

我正在学习C++,最近我一直在阅读和学习树木。我想知道,使用指针有什么好处?

例如,如果我有一个类 Node,并且我有一个名为 Function 的函数,拥有有什么区别

  Function (Node *node) 
  Function (Node node)

我知道一个把指针当作参数表,另一个则不然。但我不完全明白有什么区别。

Function(Node node)

复制参数。特别是,该函数永远无法修改原始参数,因此如果您在 Function 中操作节点,则调用 Function(node) 的代码将不会看到这些更改。

有时你想要这样,这样其他人就不会弄乱你的数据。

对于大型对象,复制数据所需的时间也是不使用指针的缺点。

使用 Function (Node *node) 您可以在函数定义中修改node的内容。

使用 Function (Node node) 无法修改函数定义中node的内容。

指针是存储另一个变量位置的变量。

因此,节点 * nodePointer 将具有如下所示的值:x000000FF,它是虚拟内存中的一个地址。 如果传递此地址,则该函数可以修改驻留在该地址的任何内容,在本例中为节点对象。 如果传递对象本身,它将是对象的副本,因此当方法返回时,原始对象将保持不变。

一般来说:

Function (Node *node) 
Function (Node node)
  • 第一个允许传递"空"值(= 0nullptr
  • 第一个可以修改对象
  • 第二个要求Node有一个复制构造函数
  • 如果sizeof(Node)> sizeof(Node*),则第二个效率较低

首先,你必须了解什么是对象。

House home;

这会为堆栈上的类"House"实例创建存储,调用构造函数并指定名称"home"以随后引用它。

对象现在占用堆栈上的空间,但堆栈只是已指定用作堆栈的内存区域。就像"中央大道"之所以如此命名,是因为当它建成时,它沿着市中心行驶,今天它只是区分一条道路和另一条道路的一种方式。

当我们谈论按值传递时,例如

int SendGift(House h, Gift g)

这意味着当我们调用这个函数时,我们会创建一个新的、本地的 House 副本,用于调用该函数进行操作。

void SendGift(House h, Gift g)
{
    h.porch.insert(g);
    g.setLocation(h);
}

"House h"和"Gift g"都是函数SendGift的临时局部变量,所以如果我们这样称呼它:

House home;
Gift gift(Gift::Dollars, 1 * 1000 * 1000);
SendGift(home, gift);

变量"home"是不变的,礼物也是如此;我们所做的所有更改都是"g"和"h",当函数结束时它们就消失了。

该守则旨在说"捐赠一百万美元并将其交付给比奇街123号的hosue"。但是因为我们按价值计算,它实际上说的是"做一百万美元的礼物。复制房屋和礼物,并将副本放入复制室,然后将它们都销毁。

它也可能非常昂贵,如果"House"对象是几Kb大,那么每次按值传递时,都必须将大量数据复制到临时中。

对于小对象,如整数,这没什么大不了的(TM)。但是对于像房子这样的大型物体,这太昂贵了。

因此,我们可能希望通过指针传递:

int SendGift(House* h, Gift* g)
{
    h->porch.insert(g);
    g->setLocation(h);
}

指针是包含地址的变量,地址是对象实例在内存中的位置。因此,我们没有将房子一砖一瓦地复制到SendGift中的临时房屋中,而是传递了地址。所以现在我们的电话

因此,通过指针(或引用)传递有两个主要原因:

  1. 当您想要允许函数修改调用它的对象的内容时,
  2. 当您希望通过避免创建输入参数的副本来最大程度地降低调用函数的成本时。

通常,当意图是 #2 而不是 #1 时,您应该将参数标记为 const。

#include <iostream>
struct BigObj
{
    BigObj() : m_useCount(0) {}
    int m_useCount;
    int m_stuff[4096];
};
void BigObjByValue(BigObj b)
{
    b.m_useCount++;
    std::cout << "BigObjByValue " << (&b) << ". m_useCount is now " << b.m_useCount << std::endl;
}
void BigObjByPtr(BigObj* b)
{
    b->m_useCount++;
    std::cout << "BigObjByValue " << (b) << ". m_useCount is now " << b->m_useCount << std::endl;
}
void BigObjByConstPtr(const BigObj* b)
{
    //b->m_useCount++; // compiler won't allow this, try uncommenting.
    std::cout << "BigObjByValue " << (b) << ". m_useCount is now " << b->m_useCount << std::endl;
}
int main()
{
    BigObj mainB;
    std::cout << "Created mainB at " << (&mainB) << " useCount = " << mainB.m_useCount << std::endl;
    BigObjByValue(mainB);
    std::cout << "in main, m_useCount = " << mainB.m_useCount << std::endl;
    BigObjByPtr(&mainB);
    std::cout << "in main, m_useCount = " << mainB.m_useCount << std::endl;
    BigObjByConstPtr(&mainB);
    std::cout << "in main, m_useCount = " << mainB.m_useCount << std::endl;
    return 0;
}

IDEe现场演示:http://ideone.com/SjkoNq