【问题标题】:Why could const member be initialized twice?为什么 const 成员可以初始化两次?
【发布时间】:2018-10-13 15:05:57
【问题描述】:

下面是一段代码sn-p,可以在vs2015中编译运行无错误

#include<iostream>
using namespace std;

class A {
    public:
        A(int b) :k(b) {}//second time
    const int k = 666;//first time
};

int main() {
    A a(555);
    cout << a.k << endl;
    return 0;
}

输出为555。但据我所知,const 对象应该只初始化一次,之后该值是不可修改的。

【问题讨论】:

标签: c++ c++11 initialization constants initializer-list


【解决方案1】:

它没有被初始化两次; default member initializer 只是被忽略了。所以对于A a(555);a.k被初始化为555

如果一个成员有一个默认的成员初始化器并且还出现在构造函数的成员初始化列表中,那么默认的成员初始化器将被忽略。

来自标准,[class.base.init]/10

如果给定的非静态数据成员同时具有默认成员 初始化器和一个mem-initializer,由指定的初始化 执行mem-initializer,非静态数据成员的默认值 成员初始化器被忽略。 [ Example:给定

struct A {
  int i = /* some integer expression with side effects */ ;
  A(int arg) : i(arg) { }
  // ...
};

A(int) 构造函数将简单地将i 初始化为arg 的值, 并且i 的默认成员初始化器中的副作用不会出现 地方。 — 结束示例 ]

另一方面,给定

class A {
public:
    A() {}            // k will be initialized via default member initializer, i.e. 666
    A(int b) :k(b) {} // k will be initialized via member initializer list, i.e. b

    const int k = 666;
};

那么对于A a;a.k 将被初始化为666

【讨论】:

  • 那句话出自哪里?我没有对此提出异议 - 正确引用它会很好。
  • @MichaelAnderson 来自我在答案中发布的链接。
  • 啊,我希望它是标准的东西。
  • @MichaelAnderson 完成。
  • 这真的很有趣,尤其是副作用的损失。
【解决方案2】:

它只初始化一次。

const int k = 666;

如果没有在构造函数中提供,将被使用。

【讨论】:

  • 建议的风格是什么:以这种方式放置默认值,还是在构造函数中作为默认参数值?
  • 在类定义中。如果对值进行特化有意义,请使用构造函数。
  • @user1997744 使用默认成员初始化器作为默认值,尤其是当有多个构造函数时;当想要覆盖它们时使用成员初始化器列表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-03
  • 1970-01-01
  • 1970-01-01
  • 2015-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多