假设我有一个不可复制的类,它有多个这样的构造函数
class Foo: boost::noncopyable
{
public:
Foo(std::string s) {...}; // construct one way
Foo(int i) {...}; // construct another way
}
现在,我要构造一个对象,并选择在运行时使用哪个构造函数:
我可以用这样的指针来做:-
boost::shared_ptr<Foo> f;
if (condition)
f.reset(new Foo(myString));
else
f.reset(new Foo(myInteger));
// common code follows
f->doSomethingComplicated(...);
但这感觉很困惑而且很慢。有没有一种简单的方法来为对象选择构造函数而不诉诸动态分配?
更多细节:上面的Foo
类只是为了说明问题。实际涉及的类是Windows Gdiplus::Bitmap
- http://msdn.microsoft.com/en-gb/library/windows/desktop/ms534420(v=vs.85).aspx
最佳答案
您可以在堆栈上使用 C++11 来执行此操作,无需放置 new 且无需复制/移动构造函数/赋值。观察:
auto factory = [&]() -> Foo
{
if (condition) {
return { myString };
} else {
return { myInteger };
}
};
Foo&& foo = factory();
foo.doSomethingComplicated();
仿函数和 Foo 实例将在堆栈上愉快地生活,不进行任何分配(可能除了在 Foo
的构造函数中复制字符串)。 Foo 超出范围时将调用其析构函数。赢了。
使用统一初始化构造返回值时,不涉及复制/移动操作。请注意,返回 myString
(隐式转换)或 Foo(myString)
将强制编译器检查对象是否可复制/可移动,即使这样的拷贝/move 可以省略。
编辑:或者,这可以更短,但更“神奇”:
Foo&& foo = [&]() -> Foo
{
if (condition) {
return { myString };
} else {
return { myInteger };
}
}();
编辑:C++11 之前,Visual Studio hacky 解决方案:
在使用隐式转换构造函数从函数返回值时,VC 似乎不检查对象是否可复制。所以这是有效的,即使它违反标准:
Foo make_foo(bool condition, const std::string&s, int i)
{
if ( condition) {
return s;
} else {
return i;
}
}
然后就这样使用它:
Foo& f = make_foo(condition, myString, myInteger);
请注意,这是另一个 VC hack,因为根据标准临时不能分配给对可变对象的引用,即它需要更改 const Foo&
,这将是这里相当有限。
不是说你应该这样处理,但这是可能的。
关于c++ - 为不可复制对象选择构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23933024/