C++ 匿名枚举的使用

C++ 匿名枚举的使用,c++,enums,C++,Enums,匿名enum声明的目的是什么,例如: enum { color = 1 }; 为什么不直接声明int color=1 (1) int color = 1; 颜色可更改(意外) 颜色无法更改 enum的另一个选项是 const int color = 1; // 'color' is unmutable enum和const int提供了完全相同的概念;这是一个选择的问题。关于enums节省空间这一流行观点,在没有内存约束的情况下,编译器足够聪明,可以在需要时优化const int [注意

匿名
enum
声明的目的是什么,例如:

enum { color = 1 };
为什么不直接声明
int color=1

(1) int color = 1;
颜色
可更改(意外)

颜色
无法更改

enum
的另一个选项是

const int color = 1;  // 'color' is unmutable
enum
const int
提供了完全相同的概念;这是一个选择的问题。关于
enum
s节省空间这一流行观点,在没有内存约束的情况下,编译器足够聪明,可以在需要时优化
const int

[注意:如果有人试图在
常量int
上使用
常量cast
,这将导致未定义的行为(这是不好的)。但是,对于
枚举
,这是不可能的。所以我个人最喜欢的是
枚举
]

颜色
可更改(意外)

颜色
无法更改

enum
的另一个选项是

const int color = 1;  // 'color' is unmutable
enum
const int
提供了完全相同的概念;这是一个选择的问题。关于
enum
s节省空间这一流行观点,在没有内存约束的情况下,编译器足够聪明,可以在需要时优化
const int


[注意:如果有人试图在
常量int
上使用
常量cast
,这将导致未定义的行为(这是不好的)。但是,对于
枚举
,这是不可能的。因此我个人最喜欢的是
枚举
]

枚举不占用任何空间并且是不变的

如果使用
const int color=1
则可以解决易变性问题,但如果有人使用
color
const int*p=&color;
)的地址,则必须为其分配空间。这可能没什么大不了的,但除非你明确希望人们能够获取
color
的地址,否则你最好阻止它

另外,在类中声明常量字段时,它必须是
static const
(对于现代C++来说并非如此),并且并非所有编译器都支持静态const成员的内联初始化



免责声明:此答案不应被视为建议对所有数值常量使用
enum
。你应该做你(或你的同事)认为更具可读性的事情。答案只是列出了人们可能更喜欢使用
枚举的一些原因

枚举不占用任何空间并且是不可变的

如果使用
const int color=1
则可以解决易变性问题,但如果有人使用
color
const int*p=&color;
)的地址,则必须为其分配空间。这可能没什么大不了的,但除非你明确希望人们能够获取
color
的地址,否则你最好阻止它

另外,在类中声明常量字段时,它必须是
static const
(对于现代C++来说并非如此),并且并非所有编译器都支持静态const成员的内联初始化



免责声明:此答案不应被视为建议对所有数值常量使用
enum
。你应该做你(或你的同事)认为更具可读性的事情。答案只是列出了人们可能更喜欢使用
enum

的一些原因,这就是所谓的枚举技巧。它的优点是可以保证不实例化任何变量,因此不存在运行时开销。大多数编译器都不会对整型常量引入任何开销。

这就是所谓的枚举技巧。它的优点是可以保证不实例化任何变量,因此不存在运行时开销。大多数编译器都不会对整型常量引入任何开销。

当您使用
enum{color=1}

你没有使用任何内存,就像
#定义颜色1

如果您声明一个变量
int color=1
然后你就占用了一个不可更改的值的内存。

当你使用
enum{color=1}

你没有使用任何内存,就像
#定义颜色1

如果您声明一个变量
int color=1

然后,您将占用一个不可更改的值的内存。

如果这是旧代码,则enum可能已用于“enum hack”


例如,您可以在以下链接中了解有关“enum hack”的更多信息:

如果这是旧代码,则enum可能已用于“enum hack”


例如,您可以在以下链接中了解有关“enum hack”的更多信息:

这种方法的一个用途是在进行模板元编程时,因为enum对象不是左值,而静态常量成员是左值。对于不允许在类定义中初始化静态整型常量的编译器,它也是一种常见的解决方法。这在中进行了解释。

在执行模板元编程时使用此方法,因为枚举对象不是左值,而静态常量成员是左值。对于不允许在类定义中初始化静态整型常量的编译器,它也是一种常见的解决方法。这在中有解释。

我看不到有提及,另一个用途是确定常量的范围。我目前正在处理使用VisualStudio2005编写的代码,现在它被移植到android-g++。在VS2005中,可以有这样的代码
enum MyOpts{OPT1=1}并将其作为MyOpts::OPT1使用-编译器并没有抱怨它,即使它是无效的。g++将此类代码报告为错误,因此一种解决方案是使用匿名枚举,如下所示:
struct MyOpts{enum{OPT1=1};},现在两个编译器都很高兴。

我没有看到提到它,另一个用途是确定常量的范围。我目前正在处理使用VisualStudio2005编写的代码,现在它被移植到
/// Floor Slope.

UPROPERTY
(
    Category = "Movement",
    VisibleInstanceOnly,

    BlueprintGetter = "BP_GetFloorSlope",
    BlueprintReadOnly,

    meta =
    (
        ConsoleVariable = "Movement.FloorSlope",
        DisplayName     = "Floor Slope",
        ExposeOnSpawn   = true,
        NoAutoLoad
    )
)

float FloorSlope = -1.f;
bool  bIsOnFloor = false;
void UMovement::SetFloorSlope(const float& FloorSlope) noexcept
    contract [[expects audit: FloorSlope >= 0._deg && FloorSlope < 90._deg]]
{
    this->bIsOnFloor = true;
    this->FloorSlope = FloorSlope;

    AUI::UI->Debug->FloorSlope = FString::Printf(L"Floor Slope: %2.0f", FloorSlope);
};
enum { False };
void UMovement::SetFloorSlope([[maybe_unused]] const decltype(False)&) noexcept
{
    this->bIsOnFloor = false;
    this->FloorSlope = -1.f;

    AUI::UI->Debug->FloorSlope = L"Floor Slope:  —";
};
SetFloorSlope(FloorSlope);
SetFloorSlope(False);
FHitResult()
{
    Init();
}

explicit FHitResult(float InTime)
{
    Init();
    Time = InTime;
}

explicit FHitResult(EForceInit InInit)
{
    Init();
}

explicit FHitResult(ENoInit NoInit)
{
}
enum EForceInit 
{
    ForceInit,
    ForceInitToZero
};
enum ENoInit {NoInit};
//A struct for temporary holding of actors (and transforms) of actors that we hit
//that don't have an ASC. Used for environment impact GameplayCues.
struct FNonAbilityTarget
{
    FGameplayTagContainer CueContainer;
    TWeakObjectPtr<AActor> TargetActor;
    FHitResult TargetHitResult;
    bool bHasHitResult;

public:
    FNonAbilityTarget()
        : CueContainer(FGameplayTagContainer())
        , TargetActor(nullptr)
        , TargetHitResult(FHitResult(ENoInit::NoInit))
        , bHasHitResult(false)
    {
    }

// (…)