我是否正确初始化了我的C ++引用变量?

时间:2009-04-15 16:13:59

标签: c++ pointers reference initialization

我已经尝试谷歌这个问题,我找不到任何我认为相关的东西。所以我一定在寻找错误的东西;尽管如此,我还是很欣赏一些建议......

Foobar &foobar = *new Foobar(someArg, anotherArg);

只是我还是看起来很臭?

我理解new关键字设计用于指针(如此):

Foobar *foobar = new Foobar(someArg, anotherArg);

但是,如果您不需要该实例上的指针,并且您想使用引用呢?或者,您是否需要显式初始化它(很像局部变量);如果是这种情况,如果我想用参数初始化怎么办?

以下不起作用(除非我做错了):

// the last argument is of type: int
Foobar &foobar(someArg, anotherArg);

...给出了编译错误:

  

初始化表达式列表被视为复合表达式       “Foobar&”类型的非const引用的无效初始化       来自临时的'int'类型

这似乎也不起作用:

Foobar &foobar = Foobar(someArg, anotherArg);

...给出了编译错误:

  

错误:类型的非const引用的初始化无效       'Foobar&'来自临时的'Foobar'

更新1:

请记住我正在返回此值,因此我不想使用局部变量;我想在堆上使用一个值,而不是堆栈:

Foobar &helloWorld()
{
    Foobar &foobar = *new Foobar(someArg, anotherArg);
    foobar.HelloWorld();
    return foobar;
}

我应该只使用指针,还是完全有效?

6 个答案:

答案 0 :(得分:11)

为什么你认为你需要使用新的和引用?为什么不:

Foobar foobar(someArg, anotherArg);

对于你的函数 - 返回一个值:

Foobar helloWorld()
{
    Foobar foobar(someArg, anotherArg);
    foobar.HelloWorld();
    return foobar;
}

或指针:

Foobar * helloWorld()
{
    Foobar * foobar = new Foobar(someArg, anotherArg);
    foobar->HelloWorld();
    return foobar;
}

如果这样做 - 调用者负责在某个时刻删除分配的对象。

从非成员函数返回的地方通常不能合理地使用引用,因为您想要引用的内容通常不再存在。

答案 1 :(得分:5)

是的,那很臭!

如果你'新'某事,将其分配给指针(或智能指针类型),因为它需要再次删除以避免内存泄漏。引用通常不被认为是您需要再次删除的内容,因此如果其他人看到该代码(将新的对象分配给引用),它可能会使它们混淆。

你可以......

const Foobar &foobar = Foobar(someArg, anotherArg);

...如果你真的想要参考。请注意,一旦foobar超出范围,它引用的临时对象将会死亡。但是,当你可以直截了当地写下来时,写作并不是很重要:

Foobar foobar(someArg, anotherArg);

您可能实际上并不需要引用...它们通常(但不是唯一地)用于方法参数的类型。这样您就可以传递看起来像对象的东西,但只有指针的大小,并且方法可以修改。引用的引用主要是为了让你编写一个拷贝构造函数(我不会在这里解释!)。

答案 2 :(得分:3)

C ++中的引用实际上并不像人们期望的那样强大,我认为混淆来自习惯于Java和C#等语言的人,这些语言没有指针并且具有可以重新分配和使用的引用。

C ++中的引用通常最适合用作变量的别名,因此您可以简化参数传递和返回值等操作。在极少数情况下,您会尝试以第一行的方式获取引用。所以通常你不需要做你想做的事情:)

第二行当然是正确的,您可以从返回引用的函数中执行返回* foobar之类的操作。

答案 3 :(得分:2)

你写得对。但请记住,通过删除& refVar释放ptr是很奇怪的。 (它可能被误认为是不是由new创建的变量。)

你应该看看GotW是否有好的做法绕过http://www.gotw.ca/gotw/我不记得那是什么课程(还有一个以上)但是阅读它比任何人都意识到的更有价值(陷阱会少一些惊喜) )

你应该尝试编写永远不会使用指针的代码。我这样做但是当我需要一个BaseObj容器时卡住了。没有解决的问题。通常我使用STL容器并在堆栈上拥有大多数变量{MyClass myVar; ...}或作为成员并根据需要传递它。

一旦你开始传递引用而不是指针并使用stl容器而不是new,它很容易删除指针。请注意,我从不使用auto_ptr。矢量,字符串,双端队列,列表和地图应该完成你需要的大部分工作。还有其他容器。

答案 4 :(得分:1)

不,你已经知道了。一个foo& “指向”实际对象,所以如果你真的想要一个foo引用,你必须取消引用foo指针。

@Neil有一个观点,不过 - 从语法上来说,这就是你得到你想要的东西,但为什么你想要它呢?

答案 5 :(得分:1)

我建议使用智能指针。您需要管理所有权,并且引用不会为您执行此操作。实际上,它会使调用者难以理解任何所有权问题。正如Scott Langham在评论中提到的那样,std :: auto_ptr会起作用。使用Boost或TR1中的shared_ptr可能是个更好的主意。

boost::shared_ptr<Foobar> helloWorld()
{
    boost::shared_ptr<Foobar> foobar(new Foobar(someArg, anotherArg));
    foobar->HelloWorld();
    return foobar;
}