0

我有一个功能

void h(A const a){...};

如果我这样做,行为是否可能会改变:

void h(A const &a){..same body as above..};

您可以根据需要自由定义类型 A。当然。

4

4 回答 4

8

在第一次重载中,h 不能改变 'a'。它在“h”的主体中用于所有目的 const。但是,这涉及复制构造函数来复制初始化“a”。

因此,在第一种情况下,它需要“A”中的可访问复制构造函数。出于同样的原因,它需要 A 中的可访问析构函数。

在第二种情况下,不需要复制初始化,因此不需要“A”的可访问复制构造函数/析构函数。

此外,在第一种情况下,如果“A”的派生对象作为参数传递,“a”将进行“切片”。第二个函数不会有“切片”问题,因为基类引用可以绑定到派生对象。因此,在这种情况下也不需要可访问的析构函数。

在 C++11 中,第一个函数将要求“A”具有可访问的“复制”或“移动”构造函数,具体取决于如何调用“h”。

于 2012-12-12T13:25:27.120 回答
1

根据您的 type 的复制构造函数中发生的情况A,是的,您可能会得到不同的行为。

如其他答案中所述,按值而不是按引用传递将导致执行复制构造函数A,这是代码采用的单独路径。如果您的类A处理某些资源,则复制该类可能最终会将该资源的不同实例传递给函数。

实际上,这一切都取决于类的A实际作用。

于 2012-12-12T13:33:26.600 回答
0

简短的回答:没有。

a更长的答案:在您的第一个示例中,在堆栈上创建了一个完整副本。无论你用什么调用函数,都会调用 A 的复制构造函数,对于你传入的参数。当函数退出时,a将调用析构函数。根据您的实施A可能会非常昂贵。

A此外,对于无法访问复制构造函数的对象、抽象类(如果是抽象的)以及如果使用派生自 的类调用,则无法调用第一个函数,函数中A接收到的副本将被切片。

第二个功能不受这些限制。

TL;DR:你永远不应该使用第一个版本(但你的里程可能会有所不同)。

于 2012-12-12T13:25:36.453 回答
0

除了其他人在这里写的关于复制构建的成本a和潜在的切片问题(如果它通过了第一种情况下的一些派生类)之外A,这些函数具有不同的签名。

如果h是某个类的成员函数并试图覆盖基类中的virtual 函数h,则这两种形式将被视为不同的函数,因为它们的签名不同。这意味着第一种形式不能超载第二种形式。

如果您随后h通过指向基类的指针调用派生类,并希望h从派生类中调用它们,则它们的签名必须相同。否则h将调用来自基类的。这可能会产生明显的差异。

于 2012-12-12T13:34:13.083 回答