在C++类声明中如何定义常量

时间:2022-10-29 12:05:38
1>使用枚举常量 enum {temp = 10};
问题1:这里的temp是每个对象都有,还是只定义了一次,所有类对象都共享这个常量?
2>使用staic const
问题2:我在类中尝试使用const int temp = 10;或者static int temp = 10;结果都会报错,而使用static const int temp = 10;不会报错,请问大神,这是为什么啊?这个常量是所有对象共享一个副本是吧?

10 个解决方案

#1


enum 比较特殊,个人认为用来定义常量非常合适,因为无法对其取地址。
类static const非常特殊,建议使用c++11的static constexpr,以保证是编译器常量。
一般static const double是运行时常量,static constexpr double是编译期常量。

c++的const的话,很模糊,又能表示编译期常量,又能表示运行期常量。
看看C#的readonly和const分得清清楚楚。
而回头看看C的const仅仅是运行时常量。
对于c++的const的“改进”,是我认为C++最操蛋的地方。

#2


原谅小弟在这里再问一个问题,实在是分不够啊,都是泪~~~
如果在函数的形参中使用const,那么实参还能给形参传递值嘛?(废话,当然可以,这个我试过,的确是可以)
那样不就相当于是形参的值被修改了吗(我就是在这里被绕住了),这与const形参相违背啊?
还是说要把实参传递值给形参理解为是const对象初始化?

#3


引用 1 楼 dustpg 的回复:
enum 比较特殊,个人认为用来定义常量非常合适,因为无法对其取地址。
类static const非常特殊,建议使用c++11的static constexpr,以保证是编译器常量。
一般static const double是运行时常量,static constexpr double是编译期常量。

c++的const的话,很模糊,又能表示编译期常量,又能表示运行期常量。
看看C#的readonly和const分得清清楚楚。
而回头看看C的const仅仅是运行时常量。
对于c++的const的“改进”,是我认为C++最操蛋的地方。

enum算是编译器常量吗?
小弟以为常量就是常量,还真没考虑过编译器常量还是运行期常量,请问大神:二者有啥区别和联系吗?

#4


enum {c=10};
和 
static const int c =10;///任何整型常量都可以这么定义
他们都可以在类内定义
表示类作用域的常量(整型常量可以用常量表达式初始化,可以当作 常量表达式 定义数组的大小)
非静态常量,不可以用常量表达式初始化,也不能当作常量表达式用
C++11 以上,则有变化,同以上不一样。
非静态成员变量,也可以在定义时候,初始化

#5


编译期常量就是会把常量直接嵌到汇编代码里面,而且可能会进行大幅度优化,
像是循环展开,复杂指令集优化之类的,不能用const_cast修改。
运行期常量,会储存在其他地方,一般用const_cast就能修改(除了一些特殊情况)。
c++11有强限制版的enum class, 不过我用的更多的还是指定“容器”:

enum : uint32_t {
 AAA = 4;
 BBB = 5,
};


这是自己喜欢的常量声明方法,不喜欢用static constexpr之类的, 毕竟搞不好就储存了一个副本浪费一点了虽然看不上的空间

一般来说,参数尽可能地声明是运行期常量就行(尽可能地加const),反正不修改参数的情况比修改参数的情况多得多。

#6


哦,忘记一个最重要的swich-case了,case语句后必须是编译期常量,而不是运行期常量:
    const int a = 1;
    switch (a)
    {
    default:
        break;
    case a:
        (void)0;
    };


比如这段代码,C++能编译成功,C不能。
稍微修改一下:
    int b = 1;
    const int a = b;
    switch (a)
    {
    default:
        break;
    case a:
        (void)0;
    };

这样a就变成运行期常量导致连C++编译器都编译不成功了。

#7


1>使用枚举常量 enum {temp = 10};
问题1:这里的temp是每个对象都有,还是只定义了一次,所有类对象都共享这个常量?
===
所有类对象都共享这个常量
2>使用staic const
问题2:我在类中尝试使用const int temp = 10;或者static int temp = 10;结果都会报错,而使用static const int temp = 10;不会报错,请问大神,这是为什么啊?这个常量是所有对象共享一个副本是吧?
===
是不是你类在的声明或者定义里对于temp的处理本身就有语法问题,所以编译不通过呢

#8


引用 6 楼 dustpg 的回复:
哦,忘记一个最重要的swich-case了,case语句后必须是编译期常量,而不是运行期常量:
    const int a = 1;
    switch (a)
    {
    default:
        break;
    case a:
        (void)0;
    };


比如这段代码,C++能编译成功,C不能。
稍微修改一下:
    int b = 1;
    const int a = b;
    switch (a)
    {
    default:
        break;
    case a:
        (void)0;
    };

这样a就变成运行期常量导致连C++编译器都编译不成功了。

非常感谢大神指导~小弟拜读了~

#9


常量是没有所谓的副本的。
因为他们连正本都没有的。
她们没有自己的地址空间的。

#10


const 表示只读,在类中定义需要用参数初始化列表来初始化。
static 为静态在整个类中被共享,比较像全局变量
const 变量作为函数的参数,其生命周期只在函数中,在函数内只读

#1


enum 比较特殊,个人认为用来定义常量非常合适,因为无法对其取地址。
类static const非常特殊,建议使用c++11的static constexpr,以保证是编译器常量。
一般static const double是运行时常量,static constexpr double是编译期常量。

c++的const的话,很模糊,又能表示编译期常量,又能表示运行期常量。
看看C#的readonly和const分得清清楚楚。
而回头看看C的const仅仅是运行时常量。
对于c++的const的“改进”,是我认为C++最操蛋的地方。

#2


原谅小弟在这里再问一个问题,实在是分不够啊,都是泪~~~
如果在函数的形参中使用const,那么实参还能给形参传递值嘛?(废话,当然可以,这个我试过,的确是可以)
那样不就相当于是形参的值被修改了吗(我就是在这里被绕住了),这与const形参相违背啊?
还是说要把实参传递值给形参理解为是const对象初始化?

#3


引用 1 楼 dustpg 的回复:
enum 比较特殊,个人认为用来定义常量非常合适,因为无法对其取地址。
类static const非常特殊,建议使用c++11的static constexpr,以保证是编译器常量。
一般static const double是运行时常量,static constexpr double是编译期常量。

c++的const的话,很模糊,又能表示编译期常量,又能表示运行期常量。
看看C#的readonly和const分得清清楚楚。
而回头看看C的const仅仅是运行时常量。
对于c++的const的“改进”,是我认为C++最操蛋的地方。

enum算是编译器常量吗?
小弟以为常量就是常量,还真没考虑过编译器常量还是运行期常量,请问大神:二者有啥区别和联系吗?

#4


enum {c=10};
和 
static const int c =10;///任何整型常量都可以这么定义
他们都可以在类内定义
表示类作用域的常量(整型常量可以用常量表达式初始化,可以当作 常量表达式 定义数组的大小)
非静态常量,不可以用常量表达式初始化,也不能当作常量表达式用
C++11 以上,则有变化,同以上不一样。
非静态成员变量,也可以在定义时候,初始化

#5


编译期常量就是会把常量直接嵌到汇编代码里面,而且可能会进行大幅度优化,
像是循环展开,复杂指令集优化之类的,不能用const_cast修改。
运行期常量,会储存在其他地方,一般用const_cast就能修改(除了一些特殊情况)。
c++11有强限制版的enum class, 不过我用的更多的还是指定“容器”:

enum : uint32_t {
 AAA = 4;
 BBB = 5,
};


这是自己喜欢的常量声明方法,不喜欢用static constexpr之类的, 毕竟搞不好就储存了一个副本浪费一点了虽然看不上的空间

一般来说,参数尽可能地声明是运行期常量就行(尽可能地加const),反正不修改参数的情况比修改参数的情况多得多。

#6


哦,忘记一个最重要的swich-case了,case语句后必须是编译期常量,而不是运行期常量:
    const int a = 1;
    switch (a)
    {
    default:
        break;
    case a:
        (void)0;
    };


比如这段代码,C++能编译成功,C不能。
稍微修改一下:
    int b = 1;
    const int a = b;
    switch (a)
    {
    default:
        break;
    case a:
        (void)0;
    };

这样a就变成运行期常量导致连C++编译器都编译不成功了。

#7


1>使用枚举常量 enum {temp = 10};
问题1:这里的temp是每个对象都有,还是只定义了一次,所有类对象都共享这个常量?
===
所有类对象都共享这个常量
2>使用staic const
问题2:我在类中尝试使用const int temp = 10;或者static int temp = 10;结果都会报错,而使用static const int temp = 10;不会报错,请问大神,这是为什么啊?这个常量是所有对象共享一个副本是吧?
===
是不是你类在的声明或者定义里对于temp的处理本身就有语法问题,所以编译不通过呢

#8


引用 6 楼 dustpg 的回复:
哦,忘记一个最重要的swich-case了,case语句后必须是编译期常量,而不是运行期常量:
    const int a = 1;
    switch (a)
    {
    default:
        break;
    case a:
        (void)0;
    };


比如这段代码,C++能编译成功,C不能。
稍微修改一下:
    int b = 1;
    const int a = b;
    switch (a)
    {
    default:
        break;
    case a:
        (void)0;
    };

这样a就变成运行期常量导致连C++编译器都编译不成功了。

非常感谢大神指导~小弟拜读了~

#9


常量是没有所谓的副本的。
因为他们连正本都没有的。
她们没有自己的地址空间的。

#10


const 表示只读,在类中定义需要用参数初始化列表来初始化。
static 为静态在整个类中被共享,比较像全局变量
const 变量作为函数的参数,其生命周期只在函数中,在函数内只读