【发布时间】:2015-01-29 11:20:48
【问题描述】:
是否可以强制 C++ 在调用函数的范围内构造对象?我的意思是明确地做返回值优化 (RVO) 所做的事情。
我有一些容器类在派生链中。由于类是用堆栈数据构造的,因此无法返回,因此我禁用了复制构造函数和赋值运算符。对于每个类,我都提供了一个迭代器。每个迭代器的构造函数只有一个参数:指向容器类的指针。要获取迭代器,我想使用这个函数:
BindPackIterator BindPack.begin(void)
{
return BindPackIterator(this);
}
在这种情况下:
for (auto i=bindpack.begin(); !i.end(); ++i) { i.run(); }
编译器发出错误,抱怨无法复制 BindPackIterator 对象。请记住,我禁用了它们。
我想要在调用函数的范围内实例化 BindPackIterator 以避免复制或移动操作。
在这种特殊情况下,我知道我可以做一个解决方法,将 begin 函数更改为返回一个 BindPack 指针,
for(BindPackIterator i=bindpack.begin(); !i.end(); ++i) { i.run(); }
我用 decltype 和这个结构做了一些实验,但没有成功:
auto BindPack::begin(void) -> BindPackIterator
{
return BindPackIterator(this);
}
这只是我目前感到沮丧的例子。在其他项目中,明显的解决方案是让函数在调用函数的范围内实例化一个对象。移动构造函数 (foo&&) 在某些情况下会有所帮助,但对于具有许多数据成员的对象,即使这样也可能效率低下。是否有允许在调用者范围内构造/实例化对象的设计模式?
【问题讨论】:
-
我可以理解为什么您可能希望在容器类上禁用复制但迭代器类应该非常小,为什么不能复制/移动?
-
迭代器应该是可复制的并且最好是可移动的。如果您的两者都不是,那么某处的设计可能有问题。关于调用者范围内的构造,这将是一个
in/out参数,对于迭代器来说相当奇怪。无论您是否正确编码,RVO 都应该处理它。 -
不可复制的迭代器没有任何意义。只是不要那样做。
-
如果您希望您的客户构造类 X 的对象,请提供类 X 的构造函数,而不是返回 X 的函数。
-
我会尝试换一种方式。您希望
BindPack.begin直接构造一个对象,而不是构造一个对象并返回一个副本。编写一个与BindPack.begin做同样事情的构造函数。
标签: c++ optimization rvo