返回对象的引用

时间:2013-10-20 06:30:46

标签: c++ pointers reference

我希望在返回对堆中创建的对象的引用时提供一些帮助。 我正在读一本名为Sam's Teach Yourself C ++的书,在第12章中,作者介绍了对堆上对象的返回引用。该示例说明了内存泄漏,作者说其中一个解决方案是在调用函数中声明对象,然后通过引用将其传递给TheFunction()。

这是一个例子:

   // Listing 12.5

     // Resolving memory leaks

     #include <iostream>



     class SimpleCat

     {

     public:

         SimpleCat (int age, int weight);

         ~SimpleCat() {}

         int GetAge() { return itsAge; }

         int GetWeight() { return itsWeight; }



     private:

         int itsAge;

         int itsWeight;

     };



     SimpleCat::SimpleCat(int age, int weight):

     itsAge(age), itsWeight(weight) {}



     SimpleCat & TheFunction();



     int main()

     {

         SimpleCat & rCat = TheFunction();

         int age = rCat.GetAge();

         std::cout << "rCat is " << age << " years old!\n";

         std::cout << "&rCat: " << &rCat << std::endl;

         // How do you get rid of that memory?

         SimpleCat * pCat = &rCat;

         delete pCat;

         // Uh oh, rCat now refers to ??

         return 0;

     }



     SimpleCat &TheFunction()

     {

         SimpleCat * pFrisky = new SimpleCat(5,9);

         std::cout << "pFrisky: " << pFrisky << std::endl;

         return *pFrisky;

     }

我的尝试:

#include <iostream>

class SimpleCat

{

public:

    SimpleCat(int age, int weight);
    ~SimpleCat() {}
    int GetAge() { return itsAge; }
    int GetWeight() { return itsWeight; }

private:
    int itsAge;
    int itsWeight;
};



SimpleCat::SimpleCat(int age, int weight):
itsAge(age), itsWeight(weight) {}


SimpleCat* TheFunction(SimpleCat&);

int main()

{
    SimpleCat * rCat;
    rCat = TheFunction(rCat);


    int age = rCat->GetAge();

    std::cout << "rCat is " << age << " years old!\n";
    std::cout << "rCat: " << rCat << std::endl;

    delete rCat;
    rCat = 0;

    system("PAUSE");
    return 0;
}






SimpleCat* TheFunction(SimpleCat& rCat)
{
    rCat = new SimpleCat(5, 9);
    std::cout << "rCat: " << rCat << std::endl;
    return rCat;
}

第二次尝试

#include <iostream>

using namespace std;


class SimpleCat

{

public:
    SimpleCat(int age, int weight)
    {
    }

    void setAge(int age)
    {
        itsAge = age;
    }
    void setWeight(int wgt)
    {
        itsWeight = wgt;
    }
    ~SimpleCat() { cout << "Object is being deleted" << endl; }

    int GetAge() { return itsAge; }
    int GetWeight() { return itsWeight; }


private:

    int itsAge;
    int itsWeight;

};



//SimpleCat * TheFunction();

SimpleCat&  TheFunction(SimpleCat* rCat)

{
    rCat = new SimpleCat(5,9);
    //pFrisky->setAge(5);
    //pFrisky->setWeight(9);
    return *rCat;
}

int main()

{

    SimpleCat * rCat;
    SimpleCat & rCat = TheFunction(&rCat);

    int age = rCat.GetAge();

    std::cout << "rCat is " << age << " years old!\n";
    system("PAUSE");
    return 0;
}

2 个答案:

答案 0 :(得分:0)

 SimpleCat * rCat;
 SimpleCat & rCat = TheFunction(&rCat);

我不认为这些行会按照你的想法去做。

第一行是声明一个变量rCat,它是一个指向cat的指针,但从不构造一个cat来与它一起使用。第二个是不起作用,因为你再次声明相同的变量。 (不能有2个rCat个对象。

但是,我仍然不太确定你要做什么。

SimpleCat rCat;
TheFunction(&rCat);

并且不要这样做:     rCat = new SimpleCat(...) 在TheFunction中,只需像你拥有它们一样进行SetAge / SetWeight调用。

没有泄漏,因为你从未打过电话。当然,TheFunction不再需要返回任何东西,因为它只是修改传入的对象。但我不确定这是否证明了作者试图达到的目的。

我想要证明作者想要的是什么,你要将你的TheFunction改为:

void TheFunction(SimpleCat& rCat) {
  rCat.SetAge(5);
  rCat.SetWeight(9);
}

答案 1 :(得分:0)

这可能有效(在某种意义上说,编译),但实际上是错误的:

    SimpleCat  TheFunction()
    {
        rCat = new SimpleCat(5,9);
//      do something with rCat if you want
        return *rCat;
    }

    int main()

    {

        SimpleCat rCat = TheFunction();

        int age = rCat.GetAge();

        std::cout << "rCat is " << age << " years old!\n";
        system("PAUSE");
        return 0;
    }

在这里,您创建新对象并返回对它的引用以初始化另一个对象,这是合法的,因为默认情况下每个C ++类都有一个复制构造函数。 但是,你会在这里遇到内存泄漏,因为你创建了一个永远不会被删除的新对象。

这可以是更好的版本:

void  TheFunction(SimpleCat*& rCat)

{
    if (rCat!=NULL) delete rCat;
    rCat = new SimpleCat(5,9);
//  do something else with rCat if you want
    return; //not required
}

int main()

{

    SimpleCat * rCat = NULL;
    TheFunction(rCat);

    int age = rCat->GetAge();

    std::cout << "rCat is " << age << " years old!\n";
    system("PAUSE");
    return 0;
}

在这里,您通过引用初始化新指针(这也是合法的)。声明指针时,声明变量,该变量具有地址,但还没有合理的内容。您将该地址的引用提供给您的函数,因此您不必返回任何内容。在函数初始化参考后,您可以在主程序中使用它。 这里没有内存泄漏,但只要所有新指针都使用NULL初始化。如果您的指针以某种方式指向垃圾,这可能会导致问题。

第三个版本(最安全的)将是:

    void  TheFunction(SimpleCat& rCat)

    {
         rCat.age = 5;
         rCat.weight = 9;
    }

    int main()

    {

        SimpleCat rCat;
        TheFunction(rCat);

        int age = rCat.GetAge();

        std::cout << "rCat is " << age << " years old!\n";
        system("PAUSE");
        return 0;
    }

在那里你将新对象的引用提供给函数,它将初始化它(即为其成员分配一些值)。该对象自声明之时就已存在(默认情况下仅由垃圾初始化),因此这也是合法的。 此处也没有内存泄漏,因为您没有为任何新对象声明内存。