【发布时间】:2012-07-10 15:40:45
【问题描述】:
考虑以下代码:
#include <vector>
class A
{
public:
A(A&&); // somewhat expensive
static std::vector<A> make_As()
{
std::vector<A> result;
result.push_back(A(3));
result.push_back(A(4));
return result;
}
private:
A(int); // private constructor
};
由于A 的移动构造函数有点昂贵(无论出于何种原因),我想避免调用它并改用emplace_back():
#include <vector>
class A
{
public:
A(A&&); // somewhat expensive
static std::vector<A> make_As()
{
std::vector<A> result;
result.emplace_back(3);
result.emplace_back(4);
return result;
}
private:
A(int); // private constructor
};
不幸的是,对于emplace_back(),实际的构造函数调用是由标准库中的某些东西完成的,它没有足够的特权来调用A 的私有构造函数。
我意识到对此可能无能为力,但我觉得由于对 emplace_back() 的调用发生在 A 的成员中,他们应该能够调用私有构造函数。
有什么解决方法吗?
我唯一能想到的就是给A添加一个friend-declaration,但是准确的类需要是A的朋友(也就是实际尝试调用构造函数的类)是特定于实现的(例如,对于 GCC,它是 __gnu_cxx::new_allocator<A>)。 编辑:刚刚意识到这样的朋友声明将允许任何人将emplace_back()A用私有构造函数构造成A的容器,所以它不会真正解决任何问题,我还不如将构造函数公开......
更新:我应该补充一点,A 的移动构造函数昂贵并不是避免调用它的唯一原因。 A 可能根本不能移动(也不能复制)。当然,这不适用于vector(因为emplace_back() 可能必须重新分配向量),但它适用于deque,它也有类似的emplace_back() 方法,但不必重新分配任何东西。
【问题讨论】:
-
旁注,但移动构造函数应该是最快的构造形式……听起来像是一个设计问题。
-
@GManNickG:使用
push_back将产生私有构造函数的成本 + 移动构造函数的成本。使用emplace_back只会产生私有构造函数的成本,所以它会更快。 -
@GManNickG:另外,避免调用移动构造函数的原因比避免其成本的原因更多。例如,A 可能根本无法移动构造(假设我将
vector替换为deque- 这将是一个合理的场景)。我将编辑答案以提及这一点。 -
@GManNickG:最后,移动构造函数可能必须很昂贵是有原因的。例如,考虑一个聚合大型
std::array成员的类。 -
@GManNickG:按值返回向量不会不会导致调用每个元素的移动构造函数。将调用向量的移动构造函数,它将简单地复制向量的内部指针/大小成员,并且根本不接触元素。
标签: c++ c++11 access-modifiers move-semantics