全球与会员职能

时间:2010-11-29 03:55:39

标签: c# c++ memory-management

我最近一直在玩c ++,并想知道为什么会有这么多全局函数。然后我开始考虑用c#编程以及如何存储成员函数,所以我想我的问题是我是否有:

public class Foo {
    public void Bar() { ... }
}

然后我做了一些愚蠢的事情,就像在列表中添加1,000,000 Foo的一样;这是否意味着我有1,000,000个 Foo 对象坐在内存中,每个对象都有自己的Bar()函数?还是会发生更聪明的事情?

感谢。

3 个答案:

答案 0 :(得分:8)

不,只有一个例子。类的所有实例都指向一个对象,该对象包含采用隐式第一个参数亲切地称为this的所有实例方法。在实例上调用实例方法时,该实例的this指针将作为第一个参数传递给该方法。这就是该方法如何知道该实例的所有实例字段和属性。

有关详细信息,请参阅CLR via C#

这当然是virtual方法的复杂化。 CLR通过C#将为您说出区别,如果您对此主题感兴趣,则高度推荐。无论哪种方式,每个实例方法仍然只有一个实例。问题在于如何解决这些方法。

答案 1 :(得分:3)

实例方法只是一个带有隐藏static参数的this方法。

virtual方法稍微复杂一些)

答案 2 :(得分:1)

在C ++中,成员函数通常不需要任何每对象存储(异常 - virtual函数 - 将在下一段中讨论)。通常,在使用函数的每个点上,编译器生成特定于CPU的机器代码以直接调用该函数,对于内联函数,可以避免调用,并且函数的影响可以最佳地集成到调用者的代码中(可以是〜对于诸如“getters and setters”之类的小函数来说,只需读取或写入一个成员变量就快10倍。

对于那些具有一个或多个虚函数的类,每个对象都有一个额外的指针指向每个类的函数指针表和其他信息。因此,每个对象都以指针的大小增长 - 通常为4或8个字节。

解决您的原始观察:C ++有更多非成员函数(通常在std命名空间中),但是命名空间最好比类更好地服务于此目的。实际上,命名空间实际上是“静态”功能和数据的逻辑接口,可以跨越许多“物理”头文件。为什么程序的逻辑API会因与物理文件相关的注意事项及其对构建时间的影响,文件修改时间戳触发的make工具等而受到影响?在命名空间位于一个标头中的简单情况下,C ++可以使用类或结构来定义相同的声明,但这样做不太方便,因为它阻止使用命名空间别名,using命名空间和Koenig查找来隐式搜索名称空间匹配函数参数的名称空间 - 在每个使用点强制使用非常明确的前缀。它还给出了错误的印象,即用户打算从内容中实例化对象。