C++11 MinGW 4.9.1 shared_ptr 和 const static class 字段结果 "Undefined reference"

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;
}

我错在哪里?

这是因为 CItem::CAPstd::make_sharedodr-used强调我的):

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

由于 std::make_shared 通过引用获取其参数,这算作 odr-use。

这意味着您还需要提供超出 class 的定义:

const int CItem::CAP  ;

或避免使用 odr,例如在这种情况下:

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

参考草案 C++11 标准部分 3.2 [basic.def.odr] 说:

An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) or a subexpression thereof. 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.

CItem::CAP 是常量表达式,除此之外的所有情况:

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

立即应用左值到右值的转换。