【发布时间】:2017-12-21 22:05:27
【问题描述】:
我有一个复制/移动探测类:
#include <iostream>
struct A
{
A()
{
std::cout << "Creating A" << std::endl;
}
~A() noexcept
{
std::cout << "Deleting A" << std::endl;
}
A(const A &)
{
std::cout << "Copying A" << std::endl;
}
A(A &&) noexcept
{
std::cout << "Moving A" << std::endl;
}
A &operator=(const A &)
{
std::cout << "Copy-assigning A" << std::endl;
return *this;
}
A &operator=(A &&) noexcept
{
std::cout << "Move-assigning A" << std::endl;
return *this;
}
};
我发现正在运行:
#include <vector>
int main(int, char **)
{
std::vector<A> v { A() };
}
产生以下输出:
Creating A
Copying A
Deleting A
Deleting A
为什么初始化不只是移动对象?我知道std::vector 可能会创建undesired copies on resize,但正如您所见,添加noexcept 在这里没有帮助(此外,我不认为调整大小导致副本适用于初始化的原因)。
如果我改为执行以下操作:
std::vector<A> v;
v.push_back(A());
我没有得到副本。
使用 GCC 5.4 和 Clang 3.8 测试。
【问题讨论】:
-
这是因为使用了
std::initializer_list构造函数。这种类型的语义是不幸的。 -
本 Q/A 解释了这种情况并提供了一些解决方法:stackoverflow.com/questions/8468774/…
-
@StoryTeller @M.M 我明白了,所以问题不在于
std::vector,而在于std::initializer_list,它显然无法转发右值引用?如果有人可以请发布正确的答案,我会接受。 -
您可以回答您的问题并接受 :) SO 模型甚至鼓励这样做。
-
@StoryTeller 感谢您的提示。我知道我可以回答自己的问题,但在这种情况下,我觉得我会从那些向我指出答案的人那里获得荣誉。无论如何,如果没有人发布答案,我会自己解决问题。
标签: c++ c++11 vector move-semantics