【发布时间】:2015-01-17 06:11:08
【问题描述】:
我有一个类 A 在构造/复制/移动时打印出一条消息
class A
{
public:
A(std::string s)
:s_(s)
{
std::cout << "A constructed\n";
}
~A()
{
std::cout << "A destructed\n";
}
A(const A& a)
:s_(a.s_)
{
std::cout << "A copy constructed\n";
}
A(A&& a)
:s_(std::move(a.s_))
{
std::cout << "A moved\n";
}
A& operator=(const A& a)
{
s_ = a.s_;
std::cout << "A copy assigned\n";
}
A& operator=(A&& a)
{
s_ = std::move(a.s_);
std::cout << "A move assigned\n";
}
std::string s_;
};
在main 中,我构造了一个A 的实例,在lambda 中按值捕获它,将该lambda 复制到std::function,最后将std::function 移动 到另一个std::function
int main()
{
A a("hello ");
std::function<void()> f = [a]{ std::cout << a.s_; };
std::function<void()> g(std::move(f));
}
这会打印出以下内容
A constructed
A copy constructed
A copy constructed
A destructed
A destructed
A destructed
为什么A的移动构造函数没有被调用?将f 移动到g 的最后一步不应该调用A 的移动构造函数吗?
【问题讨论】:
-
coliru 移动它:coliru.stacked-crooked.com/a/9815dc53d6fe8a7e。我怀疑标准是否明确规定了这里应该发生什么,显然微软选择复制而不是移动。
-
它甚至没有调用复制构造函数。构造
g的行为没有调用A的任何构造函数 -
你是对的;我一直假设第二个“构造的副本”来自
g的构造,但实际上第一个来自 lambda 捕获,第二个来自构造 lambda 之外的function。 -
仅仅改变一个对象的所有权不需要移动它。
-
GCC output 和 MSVC output 始终确定哪些行导致了哪些输出,副本不会出现在您认为的位置。
标签: c++ c++11 visual-studio-2013 lambda