花了我一段时间,但我终于构造了一个最小的示例,说明了我遇到的问题。
#include <memory>
#include <vector>
class Thing
{
};
class Box
{
public:
std::vector<std::unique_ptr<Thing>> Things;
static Box MakeBox() {Box b; return b;}
};
我的真实程序显然比这复杂得多。
GCC 4.8.3对此进行了愉快的编译。它还可以编译真实的应用程序,效果很好。
Visual Studio 2012 坚持,该代码不正确,在vc\include\xmemory0
的第606行上给我错误C2248。如果经过几英里的编译器输出,就会发现错误的 real 源是上述示例中的第11行。 (定义{{1}}的行)VS也拒绝编译我的真实应用程序,但有相同的错误。
那么,此代码正确与否?如果不正确,那么GCC为什么接受它?以及如何使其正确?如果是是正确的,那么VS为什么不编译它?我可以通过某种方式无条件强制 force VS来实际编译程序吗?
VS的输出:
Things.
答案 0 :(得分:4)
您的问题不是std::unique_ptr
,而是std::vector
。
您的编译器随附std::vector
的旧版本,该版本要求元素类型是可复制的。
按值返回(return b;
)应该调用向量的移动,但是您的std::vector
并没有实现移动。
std::unique_ptr
是可移动的,但不可复制,因此它不符合在std::vector
中使用的C ++ 11之前的要求……这一要求仍然适用于VC ++ 2012。 / p>
您最好的选择是使用较新的编译器和标准库。一种支持std::vector
上的移动语义的工具。
否则,通过消除std::vector
的副本,例如通过让MakeBox
填充输出参数而不是返回新对象,可能会有所进步。
static void MakeBox(Box& b) { /* fill Things in b provided by caller */ }
这可能是徒劳的,因为只要向量需要增长,就必须将现有元素重新定位到新存储中,并且在移动支持不完全的情况下,它将尝试复制这些元素。
答案 1 :(得分:3)
问题是Box没有移动构造函数,因此返回Box要求它具有复制构造函数(之所以不能这样做是因为unique_ptr是不可复制的)。您所要做的就是为Box定义一个移动构造函数:
range.selectNodeContents(nativeElement.firstChild);
在较新的版本中,编译器将为您生成move构造函数。