使用指针的优点/缺点

时间:2013-10-15 01:24:35

标签: c++ class pointers

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

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

  Function (Node *node) 
  Function (Node node)

我知道有人将指针作为一个参数,而另一个则没有。但我完全不明白有什么区别。

5 个答案:

答案 0 :(得分:2)

Function(Node node)

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

有时你想要这样,以便其他人不会搞砸你的数据。

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

指针是变量,用于存储另一个变量的位置

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

答案 3 :(得分:0)

一般来说:

Function (Node *node) 
Function (Node node)
  • 第一个允许传递“null”值(= 0nullptr
  • 第一个可以修改目标
  • 第二个要求Node具有复制构造函数
  • 如果sizeof(Node)> sizeof(Node*)

答案 4 :(得分:0)

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

House home;

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

对象现在占用堆栈上的空间,但堆栈只是指定用作堆栈的内存区域。就像“中央驱动器”之所以如此命名一样,因为当它建成时它沿着城镇中心向下延伸,今天它只是一种区分一条道路与另一条道路的方式。

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

int SendGift(House h, Gift g)

这意味着当我们调用这个函数时,我们会创建一个新的本地副本,我们调用它来操作函数。

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 Beech Street的主持人”。但是因为我们通过了价值,它实际上说的是“赠送一百万美元的礼物。制作房子和礼物的副本,然后将副本放入副本室,然后销毁它们。”

它也可能非常昂贵,如果“House”对象是几个Kb大,那么每次你通过值时,很多数据都必须被复制到临时。

对于像整数这样的小对象,这就是No Big Deal(TM)。但是对于大型物体,如房子,这太昂贵了。

所以我们可能希望通过指针传递:

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

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

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

  1. 如果要允许函数修改正在调用的对象的内容,
  2. 如果希望通过避免创建输入参数的副本来最小化调用函数的成本。
  3. 通常当意图是#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;
    }
    

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