对象指针如何知道取消引用多少内存?

时间:2016-06-17 19:58:14

标签: c++

所以我知道int *知道取消引用4个字节而bool *知道取消引用1。

现在如果有一个班级:

Class rectangle {
     Int l;
     Int w;
 };

现在知道矩形*是否取消引用8个字节?

如果是这样,现在假设有一个父类Shape和类矩形和从形状继承的圆。

Class circle {
     Int r;
 };

现在,如果我将Shape *指向一个矩形。如何知道取消引用8个字节而不是4个(圆圈)。

6 个答案:

答案 0 :(得分:5)

对于一个对象,编译器知道类型,因此知道大小。

对于指针,编译器仍然知道类型,因此知道大小。

但是如果指针是一个子类......那么它仍然会使用基类!编译器没有丝毫想法,因为该内存中的内容不会在运行时到达那里。可能有1 shape,可能有10亿shape秒。它们可以是形状的子类,一些circle和一些rectangle s,以及一些MöbiusParallelograms。它能做的最好的事情是取消引用shape并切掉所有非shape行为。

观察这里发生的事情:

#include <iostream>

class shape
{

};
class rectangle:public shape {
     int l;
     int w;
 };
class circle:public shape {
     int r;
 };

int main()
{
    shape s;
    rectangle r;
    circle c;

    shape* sp;

    std::cout << "Size of shape: " << sizeof(s) << std::endl;
    std::cout << "Size of rectangle: " << sizeof(r) << std::endl;
    std::cout << "Size of circle: " << sizeof(c) << std::endl;

    sp = &s;
    std::cout << "Size of dereferenced shape pointer pointing to shape: " << sizeof(*sp) << std::endl;

    sp = &r;
    std::cout << "Size of dereferenced shape pointer pointing to rectangle: " << sizeof(*sp) << std::endl;

    sp = &c;
    std::cout << "Size of dereferenced shape pointer pointing to circle: " << sizeof(*sp) << std::endl;
}

示例输出:

Size of shape: 1
Size of rectangle: 8
Size of circle: 4
Size of dereferenced shape pointer pointing to shape: 1
Size of dereferenced shape pointer pointing to rectangle: 1
Size of dereferenced shape pointer pointing to circle: 1

shapeŠ!所有这些,shape s!他们所有的个性都被剥夺了。

答案 1 :(得分:2)

  

现在,如果我Shape*指向rectangle。如何解除引用8个字节而不是4个(circle)。

编译器不知道如何做到这一点。如果您有一个Shape*,它只知道Shape,而不是关于派生类的任何内容。

一个众所周知的相关现象是object slicing。将派生类对象分配给基类对象时,会丢失基类对象中的派生类信息。

答案 2 :(得分:1)

每个指针都有一个类型;或者它指向的对象的类型。

编译器使用此类型信息来验证引用的成员(函数或数据成员)。从类型中,编译器可以计算出多少内存以进行干扰。

编辑1:
使用指向基类的指针时,编译器只知道基类项(成员和函数)。因此,取消引用基类指针可以访问基类中的项。

答案 3 :(得分:1)

有一个原因,您只能访问层次结构中类的已知成员。

'use strict';

//--- GET A REF TO CURRENT APP WITH STD ADDITONS ---
var app = Application.currentApplication()
app.includeStandardAdditions = true

var seApp = Application('System Events')

//--- Set the Clipboard so we can test for no selection ---
app.setTheClipboardTo("[NONE]")

//--- Activate the App to COPY the Selection ---
var safariApp = Application("Safari")
safariApp.activate()
delay(0.2)	// adjust the delay as needed

//--- Issue the COPY Command ---
seApp.keystroke('c', { using: 'command down' }) // Press ⌘C 
delay(0.2)	// adjust the delay as needed

//--- Get the Text on the Clipboard ---
var clipStr = app.theClipboard()
console.log(clipStr)

//--- Display Alert if NO Selection was Made ---
if (clipStr === "[NONE]") {
	var msgStr = "NO Selection was made"
	console.log(msgStr)
	app.activate()
	app.displayAlert(msgStr)
}

答案 4 :(得分:1)

  

现在知道矩形*是否取消引用8个字节?

编译器可以访问完整类型的矩形,这意味着它知道它的布局可以计算变量的对齐方式。这是计算sizeof(矩形)所必需的,当你例如有一个指针pRectanle并且你用pRectangle + 1增加它时,会使用这个值。

如果你转发声明你的矩形类,那么编译器无法访问完整类型并且会产生编译错误,如果你使用任何需要完整类型的语言特性(即解除引用指针,继承自类,......)< / p>

  

现在,如果我将Shape *指向一个矩形。如何知道取消引用8个字节而不是4个(圆圈)。

我不确定我是否理解,例如:在这里Shape* pS = pRectangle;,pS是静态类型Shape *所以当你增加这个指针或取消引用时,编译器只会看到静态类型Shape并使用它的大小。只有在使用pS调用虚拟方法时(如果有),才会使用动态类型。否则pS + 1将导致pS pt增加sizeof(Shape),如果pS指向某个数组,则不是你想要的。

答案 5 :(得分:1)

编译器不需要知道它取消引用的对象的大小。所有解除引用都会将值加载到指针中包含的地址。

当使用点(。)运算符引用结构或类的成员时,编译器从结构或类的开头获取指定偏移量处的值。

当使用箭头( - &gt;)运算符时,编译器将获取地址并将偏移量返回给所请求的元素。

当一个指针递增时,编译器将sizeof对象添加到内存中的指针值,因为对象数组是连续的,我们现在指向下一个对象。

在C ++中,基类的元素存储在派生类的数据之前,因此向下转换或向上转换不会影响指针值。

在多重继承的情况下,强制转换为基类会使编译器返回派生类中基类对象的偏移量。这就是static_castreinterpret_cast可能返回不同值的原因。