我经常遇到一种情况,我有一个数组成员变量,外部函数需要访问它的元素。我们以下面的代码为例:
class example_t
{
protected:
int* array;
size_t size;
public:
example_t(size_t size = 100) : size(size)
{
array = new[size];
// .. fill the array ..
}
~example_t()
{
delete[] array;
}
size_t get_size(void) const { return size; }
int const * get_array(void) const { return array; }
int get_array_element(size_t n) const { return array[n]; }
};
哪个界面应该是访问数组的首选方法,get_array()[n]
或get_array_element(n)
?我试图在这里考虑优化器消除重复调用的样式和可能性,例如,如果array
将一些索引存储在不同的数组中并且我们希望计算
example_t subset(1000);
for (int i = 0; i < subset.get_size(); i++)
{
result[subset.get_array_element(i)] = f(input[subset.get_array_element(i)]);
}
然后人们希望编译器能够消除重复的调用。 界面选择是否会对可能的优化产生影响?
注意:我知道我可以使用std::vector<int> array
,这只是一个例子。
答案 0 :(得分:2)
这完全取决于您的代码应该做什么,并且可能根本不会对优化产生任何影响。您的类加载指针并取消引用它,或者您的调用站点。无论哪种方式,如果你在循环中这样做,结果是完全相同的。你应该测量它以确定,但我会惊讶地发现这里有任何不同。
答案 1 :(得分:1)
由于这是C ++,可能你会使用operator []而不是get_array_element(n),但这些只是不同的语法,从性能的角度来看应该是相同的。
我认为最大的影响是编译是否可以内联这些功能。这取决于它们的大小(现在它们很小,所以是的),你编译的优化级别以及类所在的位置。如果它在头文件中,或者在与使用它的代码相同的文件中,那么是。
但是如果方法是在一个单独的C ++文件中定义的,该文件被编译为一个单独的模块,那么编译器将无法内联函数调用。在这种情况下,必须调用方法来获取每个元素都很重要。
此外,如果您将方法设为虚拟并通过基类指针访问子类,那么也会使内联失败。
如果你想对索引进行任何形式的完整性检查,那么返回指向数组的指针是不可能的。
我甚至会说,如果你要有一个返回指向数组的指针的函数,你也可以将数组本身公开。很难想象存取方法在这种情况下会有什么好处。
答案 2 :(得分:0)
如果你想为许多这样的类提出标准方法,请记住,对于非POD数据的向量(类),返回指针而不是副本可能更快例如,使用复制构造函数。)
另一方面,标准已经存在,以const和非const []运算符的形式出现,即使直接使用它们,我也倾向于模仿这些标准。