学习C ++:返回引用和绕过切片 [英] Learning C++: returning references AND getting around slicing

查看:94
本文介绍了学习C ++:返回引用和绕过切片的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个时间理解参考的魔鬼。考虑下面的代码:

I'm having a devil of a time understanding references. Consider the following code:

class Animal
{
public:
    virtual void makeSound() {cout << "rawr" << endl;}
};

class Dog : public Animal
{
public:
    virtual void makeSound() {cout << "bark" << endl;}
};

Animal* pFunc()
{
    return new Dog();
}

Animal& rFunc()
{
    return *(new Dog());
}

Animal vFunc()
{
    return Dog();
}

int main()
{
    Animal* p = pFunc();
    p->makeSound();

    Animal& r1 = rFunc();
    r1.makeSound();

    Animal r2 = rFunc();
    r2.makeSound();

    Animal v = vFunc();
    v.makeSound();
}

结果是:bark bark rawr rawr。

And the results are: "bark bark rawr rawr".

在Java的思维方式中(这显然破坏了我对C ++的概念化),结果将是bark bark bark bark。我从我的上一个问题了解到,这种差异是由于切片,我现在对切片是一个很好的了解。

In a Java way of thinking, (which has apparently corrupted my conceptualization of C++), the results would be "bark bark bark bark". I understand from my previous question that this difference is due to slicing and I now have a good understanding of what slicing is.

但是我想说,我想要一个函数返回一个Animal值,这个值实际上是一个Dog。

But let's say that I want a function that returns an Animal value that is really a Dog.


  1. 我能正确理解我能得到的最接近的是参考吗?

  2. 此外,使用rFunc接口的人是否应该看到返回的引用是分配一个Animal&?

  3. 我应该返回一个引用到一个新生成的对象,而不做愚蠢的事情(或通过切片,我上面是在rFunc? (至少我听说这很蠢。)

  1. Do I understand correctly that the closest that I can get is a reference?
  2. Furthermore, is it incumbent upon the one using the rFunc interface to see that the reference returned is assign an Animal&? (Or otherwise intentionally assign the reference to an Animal which, via slicing, discards polymorphism.)
  3. How on earth am I supposed to return a reference to a newly generated object without doing the stupid thing I did above in rFunc? (At least I've heard this is stupid.)






更新:似乎同意这样到目前为止rFunc它是非法的,这带来了另一个相关的问题:


Update: since everyone seems to agree so far that rFunc it illegitimate, that brings up another related questions:

如果我传回一个指针如何沟通给程序员的指针不是他们的删除,如果是这样?或者,我如何传达指针在任何时间(从相同的线程但不同的函数)被删除,以便调用函数不应该存储它,如果是这种情况。是唯一的方式通过评论沟通?这似乎很滑。

If I pass back a pointer how do I communicate to the programmer that the pointer is not theirs to delete if this is the case? Or alternatively how do I communicate that the pointer is subject to deletion at any time (from the same thread but a different function) so that the calling function should not store it, if this is the case. Is the only way to communicate this through comments? That seems sloppy.

*注意:所有这一切都导致了一个想法,一个模板化的shared_pimpl概念,我正在努力。希望我会学到足够的东西在几天内发布的东西。

*Note: All this is leading up to an idea for a templated shared_pimpl concept I was working on. Hopefully I'll learn enough to post something about that in a couple of days.*

推荐答案

1)如果你创建你可以返回一个指针(可能包含 std :: shared_ptr 或<$ c) $ c> std :: auto_ptr )。 (您也可以通过复制返回,但这与使用 new 运算符不兼容;它与多态性略有不兼容。)

1) If you're creating new objects, you never want to return a reference (see your own comment on #3.) You can return a pointer (possibly wrapped by std::shared_ptr or std::auto_ptr). (You could also return by copy, but this is incompatible with using the new operator; it's also slightly incompatible with polymorphism.)

2) rFunc 是错误的。不要这样做。如果您使用 new 创建对象,则通过(可选包装)指针返回。

2) rFunc is just wrong. Don't do that. If you used new to create the object, then return it through an (optionally wrapped) pointer.

你不应该。这是指针。

编辑以描述您描述的场景。更准确的说,一旦调用者调用其他(特定的)方法,返回的指针可能无效?

EDIT (responding to your update:) It's hard to picture the scenario you're describing. Would it be more accurate to say that the returned pointer may be invalid once the caller makes a call to some other (specific) method?

我建议不要使用一个模型,但如果你绝对必须这样做,你必须强制这在你的API,那么你可能需要添加一个间接级别,甚至两个。示例:将实际对象包含在包含实际指针的引用计数对象中。删除实际对象时,引用计数对象的指针设置为 null 。这是丑陋。 (可能有更好的方法,但它们可能仍然是丑陋的。)

I'd advise against using such a model, but if you absolutely must do this, and you must enforce this in your API, then you probably need to add a level of indirection, or even two. Example: Wrap the real object in a reference-counted object which contains the real pointer. The reference-counted object's pointer is set to null when the real object is deleted. This is ugly. (There may be better ways to do it, but they may still be ugly.)

这篇关于学习C ++:返回引用和绕过切片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆