无论如何都可以(不使用boost)在c ++中具有如下功能:
void foo(int x, classX &obj = *(new classX()))
classX
在我的代码库中已多次使用,并且有许多此类函数具有相似的签名(即,使用此类对象作为默认参数)。是否可以在没有过载的情况下实现这一目标?
您提供的代码当然可以编译并“运行”,但我强烈建议不要这样。
该函数返回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 */ }
}
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
写作时我咨询过的另一个问题: