C语言基础之const static

C基础之const用法

  • 以下哪一个初始化操作不合法:
int i = -1;
const int ic = i;
const int *pic = ⁣
// int *const cpi = ⁣// compile error
// cannot initialize a variable of type 'int *const'
// with an rvalue of type 'const int *'

int main()
{
    return 0;
}

 

  • 以下输出结果为:
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";

char *str5 = "abc";
char *str6 = "abc";
const char *str7 = "abc";
const char *str8 = "abc";


int main()
{

    printf("%p  %p\n", str1, str2);
    printf("%p  %p\n", str3, str4);
    printf("%p  %p\n", str5, str6);
    printf("%p  %p\n", str7, str8);

    str1[0] = '0';
    // str3[0] = '0'; // compile error
    // Cannot assign to variable 'str3' with const-qualified type 'const char [4]'
    // str5[0] = '0'; // run error: const area cannot be modified
    // str7[0] = '0'; //compile error
    // Read-only variable is not assignable

    cout << (str1 == str2) << endl;
    cout << (str3 == str4) << endl;
    cout << (str5 == str6) << endl;
    cout << (str7 == str8) << endl;
}

输出为:

0047B038  0047B03C
004795F8  004795FC
00479600  00479604
00479608  0047960C
0
0
0
0

如果为char [],会分配空间,

如果char*,指定的常量区,不可修改。如果是const char* ,从编译上就能控制不可修改。char*需要运行时才能识别。

 

  •  
  • 静态成员变量初始化
class A
{
public:
    static int a;
    // static int a = 1;  // ERROR
    // Non-const static data member must be initialized out pf line
};
int A::a = 1;
int main()
{
    cout << A::a << endl;
}

这种方案可以,

class A声明放在classA.h中,int A::a = 1; 放在classA.cpp和main.cpp中都可以。

但是放在classA.h中不可以,因为public: static int A::a" (?a@A@@2HA) 已经在 main.cpp.obj 中定义

 

class A
{
    public:
    static const int a = 1; 
};

这就是没问题的,这是因为编译器知道静态常量成员的值不会变,因此会在编译阶段优化掉,比如将所有a出现的地方都替换成1之类的。这样使得a不会***store in memory***,从而没有违反上述规则。

class A {
public:
    // 非非 非常 静非 静常
    int a = 1;
    const int b = 2;
    //const int b{2}; // another initialization method
    static int c;
    static const int d;
    static const int e = 5;
};

int A::c = 3;
// int A::c{3}; // another initialization method
const int A::d = 4;

int main() {
    cout << &A::a << " "  << &A::b << " "  << &A::c << " "  << &A::d << " "  << &A::e << endl;

    A a1;
    A a2;
    cout << &a1.a << " "  << &a1.b << " "  << &a1.c << " "  << &a1.d << " "  << &a1.e << endl;
    cout << &a2.a << " "  << &a2.b << " "  << &a2.c << " "  << &a2.d << " "  << &a2.e << endl;

    return 0;
}

程序输出为:

1 1 0004B000 00048B30 00048B6C
012FF8B0 012FF8B4 0004B000 00048B30 00048B6C
012FF8A0 012FF8A4 0004B000 00048B30 00048B6C

说明静态成员地址都一样,非静态成员地址都不一样。就算是在类内声明处赋值,地址也是一样的,应该是被优化了。

有一种说法是对e取地址则报错说找不到这个成员,这进一步说明成员e被优化掉了。自己实测是没有被优化。

 

class A
{
public:
    static int a;
};
int A::a = 1;        // 正确
static int A::a = 1; // confusing and illegal, is it static LINKAGE
// or static STORAGE DURATION
// or static MEMBERSHIP?

 

另外在上述代码我们可以发现,如果是在类外初始化静态成员,则不用再加static,因为一般语义下的static是C语言中的**“静态””静态成员“**这一语义是C++独有的且只在类内部生效

参考资料

https://blog.csdn.net/bloodfeast/article/details/99759527

 

 

1. 类的静态成员变量的声明原则:

  在.H文件中,用static 关键字进行前缀修饰即可,不可以直接进行初始化,基础变量除外。

  如果要初始化自定义的类型,则需要在CPP文件中进行初始化

  static CPerson* Police;

https://www.cnblogs.com/icmzn/p/5668862.html

 

 

 

class A
{
public:
    // 非非 非常 静非 静常
    int a = 1;
    const int b = 2;
    static int c = 3; // compile error
    // Non-const static data member must be initialized out of line
    static const int d = 4;
};

静非c禁止在类内声明处赋值。静常可以在类内声明处赋值,因为属于常量,不同对象的指向同一个地方。

 

class A
{
public:
    // 非非 非常 静非 静常
    int a;
    const int b;
    static int c;
    static const int d;
};

int A::a = 1; // compile error
// None-static data member defined out-of-line
const int A::b = 2; // compile error
// None-static data member defined out-of-line
int A::c = 3; // compile ok
const int A::d = 4;

 

 

非静态成员禁止在类外实现处赋值。

class A
{
public:
    // 非非 非常 静非 静常
    int a;
    const int b;
    static int c;
    static const int d;

    A() : a(1), b(2), c(3), d(4) { } // compile error
    // Member initializer 'c' does not name a non-static data member or base class
    // Member initializer 'd' does not name a non-static data member or base class
};

如果非常b没有在声明时赋值,则必须在处理化列表时候赋值,不然编译出错。

静非c和静常d禁止在初始化列表时赋值,因为静态变量不属于对象。

 

class A
{
public:
    // 非非 非常 静非 静常
    int a;
    const int b = 2;
    static int c;
    static const int d;

    A(int i) {
        a = 1;
        //b = 2; // compile error
        //Cannot assign to non-static data member 'b' with const-qualified type 'const int'
        c = i;
        //d = 4; // compile error
        //Cannot assign to variable 'd' with const-qualified type 'const int'
    }
};

int A::c = 3;
const int A::d = 4;

int main() {
    A a1(10);
    A a2(20);
    cout << a1.a << " "  << a1.b << " "  << a1.c << " "  << a1.d << endl;
    cout << a2.a << " "  << a2.b << " "  << a2.c << " "  << a2.d << endl;
    return 0;
}

输出为:

1 2 20 4
1 2 20 4

常量成员禁止在构造函数中赋值。

 

 

 

类型 初始化方式

类内声明

类外实现

初始化列表

构造函数

非非

N

Y

Y

非常

 

Y

N

Y

N

静非

N

Y

N

Y

静常

Y

Y

N

N

 

总结:

类内声明:静非不行;

类外实现:不是静态不行;

初始化列表:静态不行;

构造函数:常量不行。

 

 

 

 

你可能感兴趣的:(c/c++基础)