默认参数与C ++中的重载 [英] Default argument vs overloads in C++

查看:95
本文介绍了默认参数与C ++中的重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,代替

void shared_ptr::reset() noexcept;
template <typename Y>
void shared_ptr::reset(Y* ptr);

可能会想到

template <typename Y = T>
void shared_ptr::reset(Y* ptr = nullptr);

我认为此处的性能差异可以忽略不计,而第二个版本则更为简洁. C ++标准采用第一种方法有什么特殊原因吗?

I think performance difference is negligible here, and the second version is more concise. Is there any specific reason the C++ standard goes the first way?

对于Kotlin语言,已经询问了相同的问题,并且默认参数是首选.

The same question has been asked for the Kotlin language, and default argument is preferred there.

更新:

std::unique_ptr::reset()遵循默认参数设计(请参见此处 ).因此,我认为std::shared_ptr::reset()使用重载的原因是因为它们具有不同的异常规范.

std::unique_ptr::reset() follows the default argument design (see here). So I think the reason std::shared_ptr::reset() uses overloads is because they have different exception specifications.

推荐答案

关键区别在于,这两个操作实际上在语义上并不相同.

The crucial difference, is that the two operations are in fact not semantically the same.

第一个意思是将shared_ptr保留为无托管对象.第二个是让指针管理另一个对象.这是一个重要的区别.在单个函数中实现它实际上意味着我们将让一个函数执行两种不同的操作.

The first is meant the leave the shared_ptr without a managed object. The second is meant to have the pointer manage another object. That's an important distinction. Implementing it in a single function would mean that we'll essentially have one function do two different operations.

此外,每个操作可能对所讨论的类型具有不同的约束.如果将它们转储到一个函数中,则两个分支"都必须满足相同的约束,而这是不必要的限制. C ++ 17和constexpr if可以缓解这种情况,但是这些功能是在退出之前指定的.

Furthermore, each operation may have different constraints on the types in question. If we dump them into one function, then "both branches" will have to satisfy the same constraints, and that's needlessly restrictive. C++17 and constexpr if mitigate it, but those functions were specified before that exited.

最终,我认为这种设计符合Scott Meyers的建议.如果默认参数使您在语义上有所不同,则可能是另一个重载.

Ultimately, I think this design is in line with Scott Meyers' advice. If the default argument has you doing something semantically different, it should probably be another overload.

好的,请修改一下.是的,例外规范是不同的.但是就像我之前提到的,原因可以有所不同,就是功能在做不同的事情. reset成员的语义语义要求此:

Okay, so to address your edit. Yes, the exception specifications are different. But like I alluded to previously, the reason they can be different, is that the functions are doing different things. The semantics of the reset members require this:

void reset() noexcept;

效果:等同于shared_­ptr().swap(*this).

template<class Y> void reset(Y* p);

效果:等同于shared_­ptr(p).swap(*this).

那不是什么大新闻.每个函数都具有用给定的自变量(或缺少自变量)构造新的shared_ptr并进行交换的作用.那么shared_ptr构造函数做什么?根据前面的部分,他们这样做:

Not a big newsflash there. Each function has the effect of constructing a new shared_ptr with the given argument (or lack thereof), and swapping. So what do the shared_ptr constructors do? According to a preceding section, they do this:

constexpr shared_ptr() noexcept;

效果:构造一个空的shared_ptr对象.
后置条件:use_­count() == 0 && get() == nullptr.

Effects: Constructs an empty shared_­ptr object.
Postconditions: use_­count() == 0 && get() == nullptr.

template<class Y> explicit shared_ptr(Y* p);

后置条件:use_­count() == 1 && get() == p. 抛出:bad_­alloc,或者当无法获取除内存以外的资源时的实现定义的异常

Postconditions: use_­count() == 1 && get() == p. Throws: bad_­alloc, or an implementation-defined exception when a resource other than memory could not be obtained

请注意指针使用计数上的不同发布条件.这意味着第二次超载需要考虑任何内部簿记.并且很可能为此分配存储空间.这两个重载的构造函数执行不同的操作,就像我之前说的,这是将它们分成不同功能的强烈提示.可以得到更强有力的例外保证的事实进一步证明了该设计选择的合理性.

Note the different post conditions on the pointer's use count. That means that the second overload needs to account for any internal bookkeeping. And very likely allocate storage for it. The two overloaded constructors do different things, and like I previously said, that's a strong hint to separate them into different functions. The fact one can get a stronger exception guarantee is further testament to the soundness of that design choice.

最后,为什么unique_ptr两种动作都只有一个重载?因为默认值不会更改语义.它只需要跟踪新的指针值.值是null的事实(无论是从默认参数还是其他值)都不会彻底改变函数的行为.因此,只有一个过载.

And finally, why does unique_ptr have only one overload for both actions? Because the default value doesn't change the semantics. It just has to keep track of the new pointer value. The fact that value is null (either from the default argument or otherwise), doesn't change the function's behavior drastically. A single overload is therefore sound.

这篇关于默认参数与C ++中的重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆