默认(可选),作为引用的参数c ++

问题描述 投票:0回答:2

无论如何都可以(不使用boost)在c ++中具有如下功能:

void foo(int x, classX &obj = *(new classX()))

classX在我的代码库中已多次使用,并且有许多此类函数具有相似的签名(即,使用此类对象作为默认参数)。是否可以在没有过载的情况下实现这一目标?

c++ overloading pass-by-reference default-arguments
2个回答
2
投票

您提供的代码当然可以编译并“运行”,但我强烈建议不要这样。

该函数返回void,因此意味着被引用或分配的对象(或其假定所有者)不会离开该函数。因此,如果分配了它,则必须销毁它(否则,是该函数之外的其他人的问题)。

但是,甚至不可能,没有人拥有该对象或没有该对象的指针!因此,不仅那里有一个[[possible内存泄漏,而且还有一个[[guaranteed内存泄漏(如果没有传递对象的话),除非您添加另一个仅从引用派生指针的丑陋hack摧毁物体。这是非常不愉快的。

此外,即使您做到了这一点(以无泄漏的方式进行),您也无法为每个函数调用分配和销毁对象。尽管不应该过早地进行优化,但不应该通过添加常规分配和解除分配来过早地进行悲观,这不仅不必要,而且实际上会降低代码质量。最好的是:

//namespace whatever { classX dummy; //} #include <memory> void foo(int x, classX &obj = dummy) { if(std::addressof(obj) != std::addressof(dummy)) { /* do something using object */ } else { /* no object supplied */ } }

是的,这是出于良好目的而使用的全球方法。如果可以使整体感觉更好,则可以使整体成为一个单例,也可以使它成为静态类成员,所有这些都一样。无论哪种方式,您都只有一个对象,没有分配,没有泄漏,并且仍然可以根据需要将一个对象传递给函数。并且,您可以区分这两种情况。

0
投票
extern inline classX globalClassX; void foo(int x, classX &obj = globalClassX);

应该完成。

但是,我对可能干扰的static initialization order fiasco不确定。

这可以使用Meyers Singleton方法解决:

classX& getGlobalClassX() { static ClassX classX; return classX; } void foo(int x, classX &obj = getGlobalClassX);

用于演示的MCVE:

#include <cassert> #include <iostream> struct Object { inline static unsigned idGen = 1; unsigned id; const std::string name; explicit Object(const std::string &name = std::string()): id(idGen++), name(name) { } }; Object& getGlobalObj() { static Object objGlobal("global"); return objGlobal; } void doSomething(int x, Object &obj = getGlobalObj()); #define PRINT_AND_DO(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__ int main() { PRINT_AND_DO(doSomething(0)); PRINT_AND_DO(Object obj("local")); PRINT_AND_DO(doSomething(1, obj)); PRINT_AND_DO(doSomething(2)); } void doSomething(int x, Object &obj) { std::cout << "doSomething(x: " << x << ", obj: Object(" << obj.id << ", '" << obj.name << "'))\n"; }

输出:

doSomething(0); doSomething(x: 0, obj: Object(1, 'global')) Object obj("local"); doSomething(1, obj); doSomething(x: 1, obj: Object(2, 'local')) doSomething(2); doSomething(x: 2, obj: Object(1, 'global'))

Live Demo on coliru

写作时我咨询过的另一个问题:

SO: Are static data members safe as C++ default arguments?

© www.soinside.com 2019 - 2024. All rights reserved.