std :: unique_ptr可在GCC中使用,但无法在Visual Studio中编译

时间:2018-10-16 15:43:31

标签: c++ gcc visual-studio-2012

花了我一段时间,但我终于构造了一个最小的示例,说明了我遇到的问题。

#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.

2 个答案:

答案 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构造函数。