C++解引用基址指针的 ISO 标准解释

发布于 2024-12-04 11:37:52 字数 781 浏览 1 评论 0原文

我想知道标准对取消引用指向基点的指针的看法,但我在寻找它方面没有取得任何进展。以这两个类为例:

class Base
{
  public:
    virtual void do_something() = 0;
};

class Derived : public Base
{
  public:
    virtual void do_something();
};

void foo2(Base *b)
{
     Base &b1 = *b; // how this work by standard?
}

void foo()
{
  Derived *d = new Derived();
  foo2(d); // does this work by standard?
}

那么,基本上,如果类型 B 的指针指向类型 D 的对象被取消引用,切片会就地发生,还是会出现临时的?我倾向于认为临时不是一个选项,因为这意味着临时是抽象类的实例。

无论真相如何,如果有人能指出 ISO 标准中的一个或另一个,我将不胜感激。 (或者第三个,就此而言。:) )

编辑:

我提出了暂时不作为一个选项的观点,作为推理为什么它的行为方式如此的可能路线,这是非常合乎逻辑的,但我找不到确认标准,而且我不是一个普通读者。

编辑2:

通过讨论,很明显我的问题实际上是关于取消引用指针机制,而不是关于拼接或临时。我感谢大家试图为我简化它,我终于得到了最让我困惑的问题的答案:为什么我在标准中找不到任何关于这个的内容......显然这是错误的问题,但我已经得到了正确的答案。

谢谢

I would like to know standard's view on dereferencing pointer to base, but I'm not making any progress finding it. Take these two classes for example:

class Base
{
  public:
    virtual void do_something() = 0;
};

class Derived : public Base
{
  public:
    virtual void do_something();
};

void foo2(Base *b)
{
     Base &b1 = *b; // how this work by standard?
}

void foo()
{
  Derived *d = new Derived();
  foo2(d); // does this work by standard?
}

So, basically, if pointer of type B to an object of type D is dereferenced, will slicing happen in place, or temporary will emerge? I'm prone to believe that temporary is not an option, because that would mean that temporary is instance of abstract class.

Whatever the truth, I would appreciate any pointers to the ISO standard that says one or the other. (Or third, for that matter. :) )

EDIT:

I threw the point with temporary not being an option as a possible line of reasoning why it behaves the way it does, which is quite logical, but I can't find confirmation in standard, and I'm not a regular reader.

EDIT2:

Through discussion, it became obvious that my question was actually about dereferencing a pointer mechanism, and not about splicing or temporaries. I thank everyone for trying to dumb it down for me, and I finally got answer to the question the puzzled me the most: Why I can't find anything in the standard about this... Obviously it was the wrong question, but I've got the right answer.

Thnx

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

ぃ双果 2024-12-11 11:37:52
Base &b = *static_cast<Base *>(d); // does this work by standard?

是的。

但你可以简单地这样做:

Base &b = *d;

//use b polymorphically!
b.do_something(); //calls Derived::do_something()

不需要使用static_cast。毕竟,Derived 是从 Base 派生的。


回复您的编辑:

foo2(d); // does this work by standard?

是的。 Base* 类型的指针可以使用 Derived* 类型的指针进行初始化。

--

Base &b = *b; // how this work by standard?

不,他们同名。如果您的意思是,Base &b1 = *b,那么是的,可以。 b1 指的是b 所指向的对象。

Base &b = *static_cast<Base *>(d); // does this work by standard?

Yes.

But you can simply do this:

Base &b = *d;

//use b polymorphically!
b.do_something(); //calls Derived::do_something()

No need to use static_cast. After all, Derived is derived from Base.


Reply to your edit:

foo2(d); // does this work by standard?

Yes. Pointer of type Base* can be initialized with pointer of type Derived*.

--

Base &b = *b; // how this work by standard?

No. They're same name. If you mean, Base &b1 = *b, then yes, that works. b1 refers to the object pointed to by b.

总攻大人 2024-12-11 11:37:52

仅当基类的复制构造函数或赋值运算符以某种方式涉及时(例如按值传递参数),才会发生对象切片。例如,您可以通过继承 Boost 的 noncopyable 轻松避免这些错误,即使仅在 DEBUG 模式下也是如此。

指针或引用的强制转换以及取消引用都不涉及任何复制构造或赋值。从派生引用创建基引用是完全安全的,它甚至是标准的隐式转换。

Object slicing only occurs when the copy constructor or the assignment operator of the base class gets involved somehow, like in parameter passing by value. You can easily avoid these errors by inheriting from Boost's noncopyable for example, even if only in DEBUG mode.

Neither casting pointers or references nor dereferencing involve any copy construction or assignment. Making a Base reference from a Derived reference is perfectly safe, it's even a standard implicit conversion.

阳光①夏 2024-12-11 11:37:52

在我的 C++11 草案中,10 [class.driven] /1 表示

[ 注意:作用域解析运算符 :: (5.1) 可用于引用
明确的直接或间接基成员。这允许访问
已在派生类中重新声明的名称。派生类
本身可以作为受访问控制的基类;见 11.2。
指向派生类的指针可以隐式转换为指针
到一个可访问的明确基类(4.10)。 a 的左值
派生类类型可以绑定到对可访问的引用
明确的基类
(8.5.3)。 ——尾注]

在大多数实现中,您的 foo2 函数将存储 Base& b 作为Base*。显然它本身不可能是Base,因为那将是一个副本,而不是引用。由于它的行为(在运行时,而不是语法上)类似于指针而不是副本,因此不存在拼接问题。

在编辑之前的代码中,编译器会知道 Base& b 实际上是 d,它将是语法糖,甚至不会在程序集中生成指针。

In my C++11 draft, 10 [class.derived] /1 says

[ Note: The scope resolution operator :: (5.1) can be used to refer to
a direct or indirect base member explicitly. This allows access to a
name that has been redeclared in the derived class. A derived class
can itself serve as a base class subject to access control; see 11.2.
A pointer to a derived class can be implicitly converted to a pointer
to an accessible unambiguous base class (4.10). An lvalue of a
derived class type can be bound to a reference to an accessible
unambiguous base class
(8.5.3). —end note ]

In most implementations, your foo2 function will store Base& b as a Base*. It obviously can't be a Base itself, because that would be a copy, not a reference. Since it acts (at runtime, not syntactically) like a pointer instead of a copy, there's no splicing concerns.

In your code before your edit, the compiler would know that Base& b was actually d, it would be syntactic sugar, and wouldn't even generate a pointer in the assembly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文