C++标准中的过载 vs 默认参数

12

我在阅读另一个问题时,让我想到了一件事。标准通常在其描述中指定具有默认参数的函数。标准允许将这些函数写成重载吗?

例如,标准规定std::basic_string::copy的声明如下:

size_type copy(Ch* p, size_type n, size_type pos = 0) const;

一个符合标准库规范的实现是否可以将其改为两个函数,像这样?

size_type copy(Ch* p, size_type n, size_type pos) const;
size_type copy(Ch* p, size_type n) const;

在这个例子中,第二个版本可以跳过第一个版本中必须要有的 if(pos > size()) { throw out_of_range(); } 测试。这是一种微小的优化,但你可以看出这个例子的重点。


1
编译器在默认参数的情况下理论上也能进行相同的优化,不是吗? - Harper Shelby
@Harper Shelby,也许是,也许不是。那只是一个例子。我的问题实际上是关于标准库的作者是否允许这样做。 - Evan Teran
1
@HarperShelby:只有在函数调用被内联时才会执行。 - Fred Nurk
@Evan Teran:我认为这是一个非常好的问题。我的直觉是“不行,标准规定了声明,所以你必须按照那样做”,但是我在几年前参加comp.lang.c++.moderated时发现我对标准的了解非常有限。显然,可能存在更复杂的情况,程序员可以进行某种改进,这对编译器来说很难确定。 - Harper Shelby
1
@Matthieu M.:我不认为它会生成更糟糕的代码。我至少知道gcc实现了部分函数内联来解决代码重复问题。我怀疑其他编译器也有类似的聪明优化。 - Evan Teran
显示剩余2条评论
1个回答

17
一个符合标准库的实现可以改用两个函数实现,像这样吗?是的。C++标准(C++03 17.4.4.4/2-3)说:
一个实现可以在[标准库]类中声明额外的非虚成员函数签名:   --通过向成员函数签名添加带有默认值的参数;然而,同样的自由不适用于虚拟或全局或非成员函数的实现。   --通过使用具有等效行为的两个或多个成员函数签名来替换具有默认值的成员函数签名;   --为成员函数名称添加成员函数签名。
对于C++标准库中描述的成员函数签名的调用行为与实现未声明额外成员函数签名时相同。

我认为这仅适用于STL,而不适用于用户定义的代码。这可能会破坏类似于以下代码的代码:struct base { virtual void foo( int i = 0 ); }; struct derived : base { void foo(); }; struct rederived : derived { void foo(); }; 通过将默认值实现为两个不同的函数,两个函数都必须标记为虚函数,并且在通过对derived类型的引用调用rederived对象的foo()时,它将调用最终覆盖者(rederived::foo())而不是预期的derived::foo() - David Rodríguez - dribeas
@David:是的,它只适用于标准库成员函数(这是引用的标准文本第一句话所说的)。我认为问题仅涉及C++标准库类和成员函数,可能我误解了它。 - James McNellis
好像是我没有正确阅读问题。 - David Rodríguez - dribeas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接