【问题标题】:vc++ 2010/2012: std::vector of a struct containing unique_ptr compiler errorvc++ 2010/2012:包含 unique_ptr 编译器错误的结构的 std::vector
【发布时间】:2012-07-26 17:36:17
【问题描述】:

以下代码会在下面(代码之后)生成编译器错误,但如果向量直接包含 unique_ptr 则不会(请参阅注释的代码行)。任何想法为什么?

问题更关心“#if 1”块中的代码块,“#else”块产生的错误(将“#if 1”改为“#if 0”后)类似,但是更值得期待。

// MoveSemantics.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <memory>
#include <vector>

typedef std::unique_ptr<int> upi;

struct S
{
    S() : p(new int(123)) {}
    S(S&& s) : p( std::move(s.p) ) {} // NB: the move constructor is supposed to be used? (but not)
    upi p;
};

#if 1
void test()
{
    //std::vector<S> vs; // Okay
    //std::vector<upi> vupi(10); // Okay
    std::vector<S> vs(10); // Error! why in the hell does the compiler want to generate a copy constructor here??
}
#else
void test()
{
    std::vector<S> vs;

    vs.push_back( S() );
    const S& s = vs.front();
    //S& s = vs.front(); // fine!
    S s1 = std::move(s); // Error, but expected
}
#endif
int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}

编译器错误:

1> error C2248: 'std::unique_ptr<_Ty>::operator =' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          c:\program files\microsoft visual studio 11.0\vc\include\memory(1435) : see declaration of 'std::unique_ptr<_Ty>::operator ='
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          This diagnostic occurred in the compiler generated function 'S &S::operator =(const S &)'

【问题讨论】:

  • 'S &amp;S::operator =(const S &amp;)' -- 编译器不会尝试在此处调用副本 constructor...向您的类添加移动赋值运算符。
  • Doh,这看起来像是一个疏忽!今天我的代码太多了!谢谢Xeo!我怎么能接受你的评论作为答案? :D
  • 我仍然有点困惑,VS 需要赋值运算符 at all 用于 count 构造函数。它不应该那样做。
  • 没错!我基于公平的推理假设移动构造函数就足够了......
  • 不仅如此,count 构造函数应该只是值构造(也称为默认构造)对象,甚至不移动任何东西......

标签: c++ visual-c++ vector c++11 unique-ptr


【解决方案1】:

这看起来像是您的 std::lib 中的一个错误。我确信它之所以出现,是因为 vector 规范不断发展的历史。

在 C++98/03 vector 中有这个构造函数:

explicit vector(size_type n, const T& value = T(), const Allocator& = Allocator());

并且规范是 T 将默认构造一次,然后在后两个参数默认调用时复制构造的 n 次。

在 C++11 中,这变成了:

explicit vector(size_type n);
vector(size_type n, const T& value, const Allocator& = Allocator());

第二个构造函数的规范没有改变。但第一个做到了:它应该默认构造 T n 次,而不是复制(或移动)它。

我本来希望错误消息说正在使用unique_ptr 的已删除或私有复制构造函数。这表明 vector 遵循 C++98/03 规范,只是尚未更新。

但由于诊断程序抱怨的是unique_ptr复制分配,所以看起来vector 已更新,但不正确。听起来它正在使用 C++98/03 中的这个签名:

explicit vector(size_type n, const T& value = T(), const Allocator& = Allocator());

并默认构造nT's,然后将value分配给那些nT's。

【讨论】:

  • 对问题的分析和解释很透彻!就 Visual C++ 而言,似乎我们仍然生活在现代 C++ 时代的黎明。 (我用来生成错误的编译器是 Visual C++ 11 RC
【解决方案2】:

您没有包含移动赋值运算符,这是vector 要求的一部分,仅包含移动构造函数。

【讨论】:

  • 我找不到vector 的这个要求。能给个节和段号吗?
猜你喜欢
  • 2014-11-24
  • 1970-01-01
  • 2014-05-12
  • 2019-11-11
  • 2010-09-30
  • 1970-01-01
  • 1970-01-01
  • 2019-11-17
  • 2015-10-11
相关资源
最近更新 更多