gpt4 book ai didi

c++ - 为什么成员初始值设定项不能使用括号?

转载 作者:太空宇宙 更新时间:2023-11-04 12:31:18 25 4
gpt4 key购买 nike

例如,我不能这样写:

class A
{
vector<int> v(12, 1);
};

我只能这样写:

class A
{
vector<int> v1{ 12, 1 };
vector<int> v2 = vector<int>(12, 1);
};

为什么这两种声明语法之间存在差异?

最佳答案

这一选择背后的基本原理在相关的 proposal 中明确提及。对于非静态数据成员初始值设定项:

An issue raised in Kona regarding scope of identifiers:

During discussion in the Core Working Group at the September ’07 meeting in Kona, a question arose about the scope of identifiers in the initializer. Do we want to allow class scope with the possibility of forward lookup; or do we want to require that the initializers be well-defined at the point that they’re parsed?

What’s desired:

The motivation for class-scope lookup is that we’d like to be able to put anything in a non-static data member’s initializer that we could put in a mem-initializer without significantly changing the semantics (modulo direct initialization vs. copy initialization):

int x();

struct S {
int i;
S() : i(x()) {} // currently well-formed, uses S::x()
// ...
static int x();
};

struct T {
int i = x(); // should use T::x(), ::x() would be a surprise
// ...
static int x();
};

Problem 1:

Unfortunately, this makes initializers of the “( expression-list )” form ambiguous at the time that the declaration is being parsed:

   struct S {
int i(x); // data member with initializer
// ...
static int x;
};

struct T {
int i(x); // member function declaration
// ...
typedef int x;
};

One possible solution is to rely on the existing rule that, if a declaration could be an object or a function, then it’s a function:

 struct S {
int i(j); // ill-formed...parsed as a member function,
// type j looked up but not found
// ...
static int j;
};

A similar solution would be to apply another existing rule, currently used only in templates, that if T could be a type or something else, then it’s something else; and we can use “typename” if we really mean a type:

struct S {
int i(x); // unabmiguously a data member
int j(typename y); // unabmiguously a member function
};

Both of those solutions introduce subtleties that are likely to be misunderstood by many users (as evidenced by the many questions on comp.lang.c++ about why “int i();” at block scope doesn’t declare a default-initialized int).

The solution proposed in this paper is to allow only initializers of the “= initializer-clause” and “{ initializer-list }” forms. That solves the ambiguity problem in most cases, for example:

HashingFunction hash_algorithm{"MD5"};

Here, we could not use the = form because HasningFunction’s constructor is explicit. In especially tricky cases, a type might have to be mentioned twice. Consider:

   vector<int> x = 3; // error:  the constructor taking an int is explicit
vector<int> x(3); // three elements default-initialized
vector<int> x{3}; // one element with the value 3

In that case, we have to chose between the two alternatives by using the appropriate notation:

vector<int> x = vector<int>(3); // rather than vector<int> x(3);
vector<int> x{3}; // one element with the value 3

Problem 2:

Another issue is that, because we propose no change to the rules for initializing static data members, adding the static keyword could make a well-formed initializer ill-formed:

   struct S {
const int i = f(); // well-formed with forward lookup
static const int j = f(); // always ill-formed for statics
// ...
constexpr static int f() { return 0; }
};

Problem 3:

A third issue is that class-scope lookup could turn a compile-time error into a run-time error:

struct S {
int i = j; // ill-formed without forward lookup, undefined behavior with
int j = 3;
};

(Unless caught by the compiler, i might be intialized with the undefined value of j.)

The proposal:

CWG had a 6-to-3 straw poll in Kona in favor of class-scope lookup; and that is what this paper proposes, with initializers for non-static data members limited to the “= initializer-clause” and “{ initializer-list }” forms.

We believe:

Problem 1: This problem does not occur as we don’t propose the () notation. The = and {} initializer notations do not suffer from this problem.

Problem 2: adding the static keyword makes a number of differences, this being the least of them.

Problem 3: this is not a new problem, but is the same order-of-initialization problem that already exists with constructor initializers.

关于c++ - 为什么成员初始值设定项不能使用括号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58536744/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com