1

关键字将new指向创建的对象的指针返回给您,这意味着您必须继续遵守它 - 我只是担心性能可能会受到影响。

例如我面临的一个常见情况:

class cls {
    obj *x; ...
}

// Later, in some member function:
x = new obj(...);
for (i ...) x->bar[i] = x->foo(i + x->baz);  // much dereferencing

我也不太热衷于引用变量,因为我有很多*x's(例如*x, *y, *z, ...)并且不得不&x_ref = *x, &y_ref = *y, ...在每个函数的开头编写很快就会变得乏味和冗长。

确实,这样做更好吗:

class cls {
    obj x; ...    // not pointer
}
x_ptr = new obj(...);
x = *x_ptr;       // then work with x, not pointer;

那么,使用由 创建的变量的标准方法是new什么?

4

3 回答 3

5

没有其他方法可以处理由new. 创建的未命名对象的位置new始终是运行时值。这立即意味着对此类对象的每次访问都将始终无条件地要求取消引用。没有办法解决它。根据定义,这实际上是“取消引用” - 通过运行时地址访问。

&x_ref = *x您在函数开头尝试用引用“替换”指针是没有意义的。他们一无所获。在这种情况下,引用只是语法糖。它们可能会减少*源代码中运算符的数量(并且可能会增加&运算符的数量),但不会影响机器代码中物理取消引用的数量。它们将导致完全相同的机器代码包含完全相同数量的物理取消引用和完全相同的性能。

请注意,在多次重复发生取消引用的上下文中,智能编译器可能(并且将)实际读取目标地址并将其存储在 CPU 寄存器中,而不是每次都从内存中重新读取它。通过存储在 CPU 寄存器中的地址访问数据总是最快的,也就是说,它甚至比通过嵌入 CPU 指令的编译时地址访问数据还要快。因此,对可管理复杂性的重复取消引用可能不会对性能产生任何负面影响。当然,这在很大程度上取决于编译器的质量。

在您观察到重复取消引用对性能产生重大负面影响的情况下,您可能会尝试将目标值缓存在本地缓冲区中,使用本地缓冲区进行所有计算,然后当结果准备好时,通过原始指针存储它。例如,如果您有一个通过指针重复访问(读取和/或写入)数据的函数int *px,您可能希望将数据缓存在普通的局部变量中x

int x = *px;

x在整个功能中工作,最后做

*px = x;

不用说,这仅在复制对象的性能影响较低时才有意义。当然,在别名情况下您必须小心使用此类技术,因为在这种情况下,*px不会连续保持 的值。(再次注意,在这种情况下,我们使用普通变量x,而不是引用。您用引用替换单级指针的尝试完全没有结果。)

同样,这种“数据兑现”优化也可以由编译器隐式执行,假设编译器对代码中存在的数据别名关系有很好的理解。这就是 C99 风格的restrict关键字可以提供很大帮助的地方。但这是一个不同的话题。

无论如何,没有“标准”的方法可以做到这一点。最佳方法主要取决于您对每个特定代码段中存在的数据流关系的了解。

于 2013-05-11T17:02:48.873 回答
4

实例化不带new关键字的对象,如下所示:

obj x;

或者,如果您的构造函数obj接受参数:

obj x(...);

这将为您提供一个对象而不是指向它的指针。

于 2013-05-11T16:30:48.817 回答
2

您必须决定是要在堆上还是在堆栈上分配您的东西。这完全是您根据您的要求做出的决定。并且取消引用不会降低性能。您可以分配您cls的堆中,该堆将超出范围并保留obj堆栈中的实例

class cls {
  obj x;//default constructor of obj will be called
}

如果 obj 没有默认构造函数,则需要在构造函数中调用适当的构造cls函数

于 2013-05-11T16:39:32.247 回答