【问题标题】:std::unique_ptr works in GCC but won't compile in Visual Studio [duplicate]std::unique_ptr 在 GCC 中工作,但在 Visual Studio 中无法编译 [重复]
【发布时间】:2019-03-21 05:07:08
【问题描述】:

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

#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。如果我浏览了几英里的编译器输出,我发现错误的真实源是上面示例中的第 11 行。 (定义Things. 的行)VS 也拒绝编译我的真实应用程序,同样的错误。

那么,这段代码是否正确?如果它不正确,那么为什么 GCC 会接受它?以及如何使它正确?如果它正确的,那VS为什么不编译呢?有什么方法可以无条件地强制 VS 来实际编译我的程序吗?


VS 的输出:

1>------ Build started: Project: TestUniquePtr, Configuration: Debug Win32 ------
1>  Main.cpp
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(606): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1>          with
1>          [
1>              _Ty=Thing
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\memory(1447) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
1>          with
1>          [
1>              _Ty=Thing
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
1>          with
1>          [
1>              _Ty=std::unique_ptr<Thing>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(751) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<Thing>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\type_traits(743) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<Thing>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\vector(655) : see reference to class template instantiation 'std::is_empty<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=std::allocator<std::unique_ptr<Thing>>
1>          ]
1>          d:\projects\c++\testuniqueptr\testuniqueptr\main.cpp(11) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
1>          with
1>          [
1>              _Ty=std::unique_ptr<Thing>
1>          ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

【问题讨论】:

  • 你为什么用VS2012?
  • @MathematicalOrchid 这是不正确的。所有最新版本的 VS 都支持 Windows XP。您只需将平台工具集设置为与 XP 兼容的工具集。当你安装 VS 时,它要么是自带的,要么是作为一个选项,你可以在安装时检查。我最近将它与 VS 2015 一起使用,并且我已经看到它与 VS 2017 一起使用。除非你的意思是它是在 XP 上运行的最新 VS。这可能是真的。
  • VS 2012 有可笑的 C++11 支持。要获得全面支持,您需要 VS 2015(我认为是更新 3)或 2017。
  • @MathematicalOrchid 如果您需要说服任何人升级:msdn.microsoft.com/en-us/library/hh567368.aspx

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


【解决方案1】:

问题是 Box 没有移动构造函数,因此返回 Box 需要它有一个复制构造函数(它不能,因为 unique_ptr 不可复制)。您所要做的就是为 Box 定义一个移动构造函数:

Box::Box(Box&& other)
  : Things(std::move(other.Things))
{
}

对于更新的版本,编译器将为您生成移动构造函数。

【讨论】:

  • 如果Box 有十几个其他成员,这将如何工作?我是否必须明确记住也要移动所有这些? (似乎 VS 还不支持 = default 语法。)
  • 是的。真的没有办法解决这个问题(除了重构以减少成员数量)。
【解决方案2】:

你的问题不是std::unique_ptr,而是std::vector

您的编译器带有旧版本的 std::vector,它要求元素类型是可复制的。

按值返回 (return b;) 应该调用向量的移动,但您的 std::vector 没有实现移动。

std::unique_ptr 可移动但不可复制,因此它不符合在 std::vector 中使用的 C++11 之前的要求...这一要求仍然适用于 VC++ 2012。

您最好的选择是使用更新的编译器和标准库。一种支持std::vector 上的移动语义。

否则,您可能会通过消除std::vector 的副本来取得一些进展,例如,通过让MakeBox 填充输出参数而不是返回新对象。

static void MakeBox(Box& b) { /* fill Things in b provided by caller */ }

不过,这可能是徒劳的,因为每当向量需要增长时,它必须将现有元素重新定位到新的存储中,并且在移动支持不完整的情况下,它会尝试复制这些。

【讨论】:

  • 我现在隐约记得这些问题。甚至想到缺少 NRVO 和 C++17 的保证复制省略,但没有想到缺少移动构造函数:D
  • 我不相信这是答案。 MSVS2012 不会自动生成移动构造函数,因此 Box 不可移动。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-07
  • 1970-01-01
相关资源
最近更新 更多