简体   繁体   English

C ++ 11 MinGW 4.9.1 shared_ptr和const静态类字段结果“未定义引用”

[英]C++11 MinGW 4.9.1 shared_ptr and const static class field result “Undefined reference”

#include <memory>

class CItem
{
  private:
    int m_inner;
  public:
    static const int CAP = 1;
    CItem(int temp) : m_inner(temp) {}
};

typedef std::shared_ptr<CItem> TPItem;

int main()
{
  int tttt = CItem::CAP;
  CItem *temp = new CItem(CItem::CAP);
  TPItem temp2(temp);
  TPItem temp3 = std::make_shared<CItem>(tttt);
  TPItem temp4 = std::make_shared<CItem>(CItem::CAP); //On MinGW there error: "undefined reference to `CItem::CAP'"

  return 0;
}
  • on Visual Studio 2012 it work normal. 在Visual Studio 2012上,它可以正常工作。
  • on minGW32 4.9.1 it say "undefined reference" for static const field of class when try create shared pointer with make_shared. 在minGW32 4.9.1上,当尝试使用make_shared创建共享指针时,它为类的静态const字段说“未定义引用”。
  • other methods: 其他方法:
  • copy this field to int and create shared with this int - work . 将此字段复制到int并与此int- work创建共享。
  • create class object with new - work . 用new- work创建类对象。

Where my fault? 我的错在哪里?

This is because CItem::CAP is odr-used by std::make_shared ( emphasis mine ): 这是因为CItem::CAPODR使用的通过std::make_shared重点煤矿 ):

Informally , an object is odr-used if its address is taken, or a reference is bound to it , and a function is odr-used if a function call to it is made or its address is taken. 非正式地如果使用对象的地址或将引用绑定到该对象,则该对象为odr-use, 如果对该对象进行函数调用或使用其地址,则该函数为odr-used。 If an object or a function is odr-used, its definition must exist somewhere in the program; 如果使用对象或函数,则其定义必须存在于程序中的某个位置。 a violation of that is a link-time error. 违反此规定是链接时错误。

Since std::make_shared takes its arguments by reference, this counts as an odr-use. 由于std :: make_shared通过引用接受其参数,因此算作odr使用。

which means you are required to provide an out of class definition as well: 这意味着您还需要提供类外定义:

const int CItem::CAP  ;

or avoid the odr-use such as in this case: 或避免在这种情况下使用odr:

TPItem temp3 = std::make_shared<CItem>(tttt) ;

For reference the draft C++11 standard section 3.2 [basic.def.odr] says: 作为参考,C ++ 11标准草案第3.2[basic.def.odr]说:

An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) or a subexpression thereof. 除非表达式是未评估的操作数(第5条)或其子表达式,否则可能会对其进行评估。 A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) is immediately applied . 除非其对象满足在常量表达式中出现的要求(5.19)并且立即应用左值到右值转换(4.1)否则使用其名称显示为可能评估的表达式的变量。

CItem::CAP is a constant expression and in all the cases except this one: CItem::CAP是一个常数表达式,在除此以外的所有情况下:

TPItem temp4 = std::make_shared<CItem>(CItem::CAP);

the lvalue-to-rvalue conversion is applied immediately. 左值到右值的转换将立即应用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM