【问题标题】:constexpr array not definedconstexpr 数组未定义
【发布时间】:2014-10-23 18:52:14
【问题描述】:

我使用 c++11。我正在尝试初始化一个多维数组。第一次尝试是

const static int COORDINATES[4][4][2]={{{-1,-1},{0,0},{1,1},{2,0}},
                                       {{-1,1},{0,0},{1,-1},{0,-2}},
                                        {{1,1},{0,0},{-1,-1},{-2,0}},
                                         {{1,-1},{0,0},{-1,1},{0,2}}}; 

编译器抱怨 constexpr,所以我写了

constexpr const static int COORDINATES[4][4][2]={{{-1,-1},{0,0},{1,1},{2,0}},
                                       {{-1,1},{0,0},{1,-1},{0,-2}},
                                        {{1,1},{0,0},{-1,-1},{-2,0}},
                                         {{1,-1},{0,0},{-1,1},{0,2}}};

没有错误,但是当我在方法中使用数组时,会出错。没看懂……

void LShape::rotateShape(Square* cloneSquares) {
    int var=COORDINATES[1][1][1]; //no problems
    int x=2;
    var=COORDINATES[0][x][0]; //error 'not defined' because of x
                             //if changed to number, works
}

错误:

LShape.cpp:23: referencia a `LShape::COORDINATES' sin definir //reference to L...S not defined

第 23 行是 COORDINATES 的第二次使用

我的完整代码,LShape 标头

#ifndef LSHAPE_H 
#define LSHAPE_H

#include "Square.h"
#include "EmptySquare.h"
#include "Shape.h"

class LShape : public Shape {

public:
LShape();
LShape(const LShape& orig);
virtual ~LShape();

inline int getState() {return state;}
inline int getNUMBER_OF_STATES() {return NUMBER_OF_STATES;}
inline int getNUMBER_OF_SQUARES() {return NUMBER_OF_SQUARES;} 

void rotateShape(Square* cloneSquares);


private:
int state;
static const int NUMBER_OF_STATES=4;
static const int NUMBER_OF_SQUARES=4;


constexpr const static int INITIAL_COORDINATES[3][2]={{1,0},{1,0},{1,1}};

constexpr const static int COORDINATES[4][4][2]={{{-1,-1},{0,0},{1,1},{2,0}},
                                       {{-1,1},{0,0},{1,-1},{0,-2}},
                                        {{1,1},{0,0},{-1,-1},{-2,0}},
                                         {{1,-1},{0,0},{-1,1},{0,2}}}; 


};
#endif  /* LSHAPE_H */

L形状代码

#include "../../include/LShape.h"

LShape::LShape() : Shape(){
    //numberSquares=4;
    //squares = new Square[numberSquares];
}

LShape::~LShape(){
    //dtor
}

LShape::LShape(const LShape& other){
    //copy ctor
}


void LShape::rotateShape(Square* cloneSquares) {

    int var=COORDINATES[1][1][1]; //no problems
    int x=2;
    var=COORDINATES[0][x][0]; //error not defined
}

顺便说一句,我是 C++ 的新手,不要对我不好 :)

编辑:我在 linux (GCC) 中使用默认编译器,IDE 使用以下命令

g++ -std=c++11   -c -g -MMD -MP -MF "build/Debug/GNU-Linux-x86/src/shape/LShape.o.d" -o build/Debug/GNU-Linux-x86/src/shape/LShape.o src/shape/LShape.cpp

【问题讨论】:

  • 在定义坐标之前包含 shape.h !
  • @Christophe 我看不出有什么问题...坐标仅在 LShape 中,而不是形状
  • @Piotr S. 我在 linux (GCC) 中使用默认编译器,IDE 使用以下命令 g++ -std=c++11 -c -g -MMD -MP -MF " build/Debug/GNU-Linux-x86/src/shape/LShape.od" -o build/Debug/GNU-Linux-x86/src/shape/LShape.o src/shape/LShape.cpp

标签: c++ arrays c++11 constexpr


【解决方案1】:

数组是类成员这一事实是这个难题的重要组成部分。

static constexpr(在某些情况下,还有const)类成员有一个特殊规则,即如果它们从未被使用过,则不需要定义。但是您的程序确实使用了该变量,因此根据 C++ 标准,您需要一个定义。

2x 之间的行为发生变化的原因是,在前一种情况下,优化器能够消除对数组的运行时访问。但是你不能依赖这个1,规则是如果有odr-use需要定义。

这是第 9.4.2 节 ([class.static.data]) 中的完整规则:

如果非易失性const static 数据成员是整数或枚举类型,它在类定义中的声明可以指定一个brace-or-equal-initializer,其中每个初始化器-clause 是一个 assignment- 表达式 是一个常量表达式 (5.19)。可以在类定义中使用 constexpr 说明符声明文字类型的 static 数据成员;如果是这样,它的声明应指定一个 brace-or-equal-initializer,其中作为 assignment-expression 的每个 initializer-clause 都是一个常量表达式。 [ 注意:在这两种情况下,成员都可能出现在常量表达式中。 — end note ] 如果该成员在程序中被 odr-used (3.2) 使用,则该成员仍应在命名空间范围内定义,并且命名空间范围定义不应包含初始化程序。


在其他情况下,需要进行优化。例如,您可以使用

var = sizeof (char[COORDINATES[0][2][0]]);

这绝不是 COORDINATES 的 odr 使用。但是这种保证只在需要常量表达式的地方做出,比如在数组绑定中,而不是一般情况下。

如果您尝试使用负数组界限,当然会出现问题。所以也许你更喜欢:

enum { varc = COORDINATES[0][2][0] };
var = varc;

关键是在绝对必须在编译时评估的上下文中使用它。

【讨论】:

  • 我把 constexpr const int LShape::COORDINATES[4][4][2];在标题的末尾,现在编译。希望不要再出问题了,哈哈。谢谢你的解释。
【解决方案2】:

我删除了 `constexpr' 并能够在 http://www.compileonline.com/compile_cpp_online.php 编译代码

const static int COORDINATES[4][4][2]={{{-1,-1},{0,0},{1,1},{2,0}},
                                      {{-1,1},{0,0},{1,-1},{0,-2}},
                                      {{1,1},{0,0},{-1,-1},{-2,0}},
                                      {{1,-1},{0,0},{-1,1},{0,2}}}; 


void LShape_rotateShape() 
{

    int var=COORDINATES[1][1][1]; //no problems
    int x=2;
    var=COORDINATES[0][x][0]; //error not defined
}

我使用以下编译器成功编译:

  • C++ 在线(GNU GCC 版本 4.8.1)
  • C++11 在线(GNU GCC 版本 4.7.2)

【讨论】:

    猜你喜欢
    • 2011-11-17
    • 2013-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    相关资源
    最近更新 更多