在C ++中使用花括号实例化对象是什么意思?

时间:2022-08-15 16:56:32

Let's say I have a struct defined as:

假设我有一个结构定义为:

typedef
struct number{
    int areaCode;
    int prefix;
    int suffix;
} PhoneNumber;

When I create an instance of this struct, if I use the following syntax:

当我创建此结构的实例时,如果我使用以下语法:

PhoneNumber homePhone = {858, 555, 1234};

...which constructor is it calling? The default constructor, or the copy constructor, or none at all because it's not calling 'new'?

...它正在调用哪个构造函数?默认构造函数,或复制构造函数,或者根本没有,因为它没有调用'new'?

The real purpose of this question is to figure out how I can add a fourth field. So I want to re-define my struct as:

这个问题的真正目的是弄清楚如何添加第四个字段。所以我想重新定义我的结构:

typedef
struct number{
    int areaCode;
    int prefix;
    int suffix;
    int extension; // NEW FIELD INTRODUCED
} PhoneNumber;

So now, I can create new PhoneNumber objects with FOUR fields:

所以现在,我可以用FOUR字段创建新的PhoneNumber对象:

PhoneNumber officePhone = {858, 555, 6789, 777}

However, I have hundreds of these PhoneNumber instances already created with only 3 fields (xxx, xxx, xxxx). So I don't want to go through and modify EVERY single instantiation of my PhoneNumber object that is already defined. I want to be able to leave those alone, but still be able to create new phone number instances with FOUR fields. So I am trying to figure out how I can overwrite the constructor so that my existing three-parameter instantiations will not break, but it will also support my new four-parameter instantiations.

但是,我已经创建了数百个这样的PhoneNumber实例,只有3个字段(xxx,xxx,xxxx)。因此,我不想通过修改已定义的PhoneNumber对象的每个单一实例化。我希望能够独自留下这些,但仍然能够使用FOUR字段创建新的电话号码实例。所以我试图找出如何覆盖构造函数,以便我现有的三参数实例化不会中断,但它也将支持我的新的四参数实例化。

When I try to define an overriding default constructor that takes 3 fields and sets the fourth to a default value '0', I get errors (in the instantiation part of the code, not the constructor definition) complaining that my object must be initialized by constructor, not by {...}. So it seems that if I do override the default constructor, I can no longer use curly braces to create my new objects?

当我尝试定义一个覆盖3个字段并将第四个设置为默认值'0'的覆盖默认构造函数时,我得到错误(在代码的实例化部分,而不是构造函数定义)抱怨我的对象必须由构造函数,而不是{...}。所以,如果我覆盖默认构造函数,我似乎不能再使用花括号来创建我的新对象了?

Sorry if this strays away from the original questions completely.

对不起,如果这完全偏离了原来的问题。

7 个解决方案

#1


The members are actually copy-initialized. The default constructor for each one is not called and no operator= is involved contrary to what some other answers suggest. It can be shown by a software called geordi - alternatively by reading through the Standard. I'll show the "fun" way using that software. It has got a class tracked::B that can show us when constructors/copy-constructors or destructors/copy assignment operators are called. The output it shows is (TRACK limits tracking to the statement following it):

成员实际上是复制初始化的。不调用每个默认构造函数,并且没有涉及operator =,这与其他一些答案所暗示的相反。它可以通过一个名为geordi的软件显示 - 或者通过阅读标准来显示。我将展示使用该软件的“有趣”方式。它有一个跟踪的类:: B,它可以在调用构造函数/复制构造函数或析构函数/复制赋值运算符时向我们显示。它显示的输出是(TRACK限制跟踪它后面的语句):

B1*(B0) B1~

I used this code

我用过这段代码

struct T { tracked::B b; }; int main() { tracked::B b; TRACK T t = { b };  }

As you see, the second B object - which is the member within the local variable t, is copy initialized from the other object b. Of course, no assignment operator is activated. You can read about it in 12.6.1/2 in the Standard, if you wish.

如您所见,第二个B对象 - 它是局部变量t中的成员,是从另一个对象b初始化的副本。当然,没有激活赋值运算符。如果您愿意,可以在标准中的12.6.1 / 2中阅读。

The same, by the way, is true with arrays (which are likewise aggregates). Many people believe that objects that are member of arrays must have a type that has a default constructor. But that's not true. They can just be copy initialized by another object of their type and it will work fine.

顺便说一句,对于数组(同样是聚合)也是如此。许多人认为作为数组成员的对象必须具有具有默认构造函数的类型。但事实并非如此。它们只能由其他类型的对象进行初始化,并且可以正常工作。

All other elements that were not explicitly initialized in the aggregate are value initialized. Value-initialization is a mixture of default initialization and zero initialization. Actually, if a member has a type that has a user declared constructor, then that constructor is invoked. If it has a type that does not have a user declared constructor, then each member of it is value initialized. For built-in types (int, bool, pointers, ...) a value initialization is the same as zero initialization (that means that such a variable will become zero). The following will initialize each member to zero - except the first (a), which will be one:

未在聚合中显式初始化的所有其他元素都是值初始化的。值初始化是默认初始化和零初始化的混合。实际上,如果成员的类型具有用户声明的构造函数,则调用该构造函数。如果它的类型没有用户声明的构造函数,那么它的每个成员都是值初始化的。对于内置类型(int,bool,pointers,...),值初始化与零初始化相同(这意味着这样的变量将变为零)。以下将每个成员初始化为零 - 除了第一个(a),它将是一个:

struct T { int a, b, c; }; int main() { T t = { 1 }; }

Those initialization rules are scary, indeed - especially because the 2003 revision of C++ introduced that value initialization. It wasn't part of the Standard as of 1998. If you are more interested in those brace enclosed initializations, you can read How to initialize nested structures in C++?.

确实,这些初始化规则是可怕的 - 特别是因为2003年版的C ++引入了值初始化。它不是1998年标准的一部分。如果你对那些大括号括起来的初始化更感兴趣,你可以阅读如何在C ++中初始化嵌套结构?

#2


It's not calling the default ctor, as others have written. Conceptually it's the same, but in practice, you'll find no function call in the assembly code.

正如其他人所写的那样,它并没有调用默认的ctor。从概念上讲它是一样的,但在实践中,你会发现汇编代码中没有函数调用。

Instead, the members remain uninitialized; you're initializing them with the curly-brace construct.

相反,成员仍然没有初始化;你是用花括号结构初始化它们的。

Interestingly enough, this:

有趣的是,这个:

PhoneNumber homePhone = {858, 555, 1234};

Results in this assembly (GCC 4.0.1, -O0):

此程序集中的结果(GCC 4.0.1,-O0):

movl  $858, -20(%ebp)
movl  $555, -16(%ebp)
movl  $1234, -12(%ebp)

Not many surprises there. The assembly is inline the function containing the above C++ statement. The values (starting with $) are moved (movl) into offsets into the stack (ebp register). They're negative because the memory locations for the struct members precede the initialization code.

那里没什么惊喜。程序集内联包含上述C ++语句的函数。将值(以$开头)移动(movl)到堆栈中的偏移量(ebp寄存器)。它们是负面的,因为struct成员的内存位置在初始化代码之前。

If you don't fully initialize the struct, i.e. leave out some members like so:

如果你没有完全初始化结构,即省略一些像这样的成员:

PhoneNumber homePhone = {858, 555};

... then I get the following assembly code:

...然后我得到以下汇编代码:

movl  $0, -20(%ebp)
movl  $0, -16(%ebp)
movl  $0, -12(%ebp)
movl  $858, -20(%ebp)
movl  $555, -16(%ebp)

Seems as if the compiler then actually does something very similar to calling the default constructor, followed by assignment. But again, this is inline in the calling function, not a function call.

看起来好像编译器实际上做了一些非常类似于调用默认构造函数的东西,然后是赋值。但同样,这是在调用函数内联,而不是函数调用。

If on the other hand you define a default constructor that initializes the members, to the given values, like so:

另一方面,如果您定义了一个默认构造函数,它将成员初始化为给定值,如下所示:

struct PhoneNumber {
  PhoneNumber()
    : areaCode(858)
    , prefix(555)
    , suffix(1234)
  {
  }

  int areaCode;
  int prefix;
  int suffix;
};

PhoneNumber homePhone;

Then you get assembly code that actually calls a function, and initializes the data members via a pointer to the struct:

然后你获得实际调用函数的汇编代码,并通过指向struct的指针初始化数据成员:

movl  8(%ebp), %eax
movl  $858, (%eax)
movl  8(%ebp), %eax
movl  $555, 4(%eax)
movl  8(%ebp), %eax
movl  $1234, 8(%eax)

Each line that goes movl 8(%ebp), %eax sets the pointer value (eax register) to the beginning of the struct's data. In the other lines, eax is used directly, with an offset of 4 and an offset of 8, similar to the direct stack addressing in the previous two examples.

每个行都是movl 8(%ebp),%eax将指针值(eax寄存器)设置为struct数据的开头。在其他行中,eax直接使用,偏移量为4,偏移量为8,类似于前两个示例中的直接堆栈寻址。

Of course all of this is specific to the compiler implementation, but I'd be surprised if other compilers did something extraordinarily different.

当然所有这些都是编译器实现所特有的,但如果其他编译器做了一些非常不同的事情,我会感到惊讶。

#3


A struct in C++ is like a class. The default constructor is being called. Afterwards, each field is copied with its assignment operator.

C ++中的结构就像一个类。正在调用默认构造函数。然后,使用其赋值运算符复制每个字段。

#4


Initialization is, at least to me, one of the toughest parts of the C++ standard. The syntax you are using: Aggregate x = { 1, 2, 3, 4 }; defines the initialization of an aggregate type with the first four members assigned values 1, 2, 3 and 4.

至少在我看来,初始化是C ++标准中最棘手的部分之一。您正在使用的语法:聚合x = {1,2,3,4};定义聚合类型的初始化,前四个成员分配值1,2,3和4。

As a note to your particular case (the struct has grown from 3 to 4 elements), the fields not present in the initialization list between the curly braces will be value initialized, which in particular for scalar types is equivalent to zero initialization which is itself the same as assigning 0. Thus your fourth element will be initialized to 0.

作为特定情况的注释(结构从3个元素增长到4个元素),花括号之间的初始化列表中不存在的字段将被初始化值,特别是对于标量类型而言,它等同于零初始化,它本身就是零与赋值0相同。因此,您的第四个元素将初始化为0。

References

It is all defined in the C++ standard, chapter 8.5, and more precisely in 8.5.1 Aggregates. Aggregates will not be initialized with any implicitly declared default constructor. If you use the syntax above you are asking the compiler to initialize the given fields with the provided values. Any extra field in the aggregate shall be value initialized

它全部在C ++标准的第8.5章中定义,更确切地说在8.5.1 Aggregates中定义。不会使用任何隐式声明的默认构造函数初始化聚合。如果使用上面的语法,则要求编译器使用提供的值初始化给定字段。聚合中的任何额外字段都应初始化值

Now, value initialization is defined as a call to the user defined default constructor if the type is a class with such constructor. If it is an array or a non-union class without user defined constructor then each one of the member attributes will be value initialized. Otherwise the object will be zero initialized, which then again is defined as...

现在,如果类型是具有此类构造函数的类,则值初始化定义为对用户定义的默认构造函数的调用。如果它是没有用户定义构造函数的数组或非联合类,则每个成员属性都将被初始化值。否则,对象将初始化为零,然后再次定义为...

Zero initialization is defined as setting the value to 0 for scalar types. For classes each class data member and base class will be zero initialized. For unions, the first member (only) will be zero initialized, for arrays all members will be zero initialized.

零初始化定义为将标量类型的值设置为0。对于类,每个类的数据成员和基类将初始化为零。对于联合,第一个成员(仅)将初始化为零,对于数组,所有成员将初始化为零。

#5


It's effectively calling the default ctor; what's happening is a struct is allocated, and each value is assigned used default "=".

它有效地调用了默认的ctor;发生了什么是分配结构,并为每个值分配使用默认值“=”。

#6


However, I have hundreds of these PhoneNumber instances already created with only 3 fields (xxx, xxx, xxxx). So I don't want to go through and modify EVERY single instantiation of my PhoneNumber object that is already defined.

但是,我已经创建了数百个这样的PhoneNumber实例,只有3个字段(xxx,xxx,xxxx)。因此,我不想通过修改已定义的PhoneNumber对象的每个单一实例化。

No problem, you just call update-instance-for-redefined-class and ..... er, nevermind. Proceed to mark this "unhelpful"

没问题,你只需要调用update-instance-for-redefined-class和.....呃,没关系。继续标记这个“无益”

#7


There is no constructor on your type involved, so the existing three-parameter syntax would need to be modified at aggregate initialisation site.

您的类型没有构造函数,因此需要在聚合初始化站点修改现有的三参数语法。

Unless semantics of your newly added field ie. that new field type, are 'zeroed design-aware' ( idiom recommended by .NET programming, Brad and Co etc in design guidelines nonsense), you

除非您新添加的字段的语义,即。新的字段类型,'归零设计意识'(.NET编程推荐的成语,Brad和Co等在设计指南中无意义),你

cannot :

a) provide something more meaningful as either C++ default parameters if with some magic there was a method involved ( deault/optional params soon to be available in mass-market C# shop near the grocers web 4.0 and for old COM )

a)提供一些更有意义的东西作为C ++默认参数,如果有一些魔法有一个方法涉及(deault / optional params很快就可以在杂货店web 4.0附近的大众市场C#商店和旧COM中使用)

nor can you

你也不是吗?

b) follow the C# like pattern of designing value types with invalid value markers as 0s ( which is in this case arguably very bad and bad in general if you do not have control over the constants - something source-level libraries do very well and all-JavaTM MS -like frameworks suck at ).

b)遵循C#类似设计值类型的模式,将无效值标记设置为0(在这种情况下,如果您无法控制常量,这通常会非常糟糕和糟糕 - 某些源级库非常好并且所有-JavaTM类似于MS的框架很糟糕。

In short, if 0 is a valid value you are stuffed and something most compiler writers saw as useful before any managed style or idiom ever existed; but it isn't necessarily right.

简而言之,如果0是有效值,那么大多数编译器编写者在任何托管样式或习惯用法存在之前都认为它是有用的;但它不一定是对的。

Anyway, you best chance isn't C++, or C#. It is code-generation, ie. more liberal meta-programming than modern C++ 'templating' pushes on.. You'll find it similar to JSON array annotation and could use either spirit or (my advice would be) roll your own utils. It helps in the long run, and eventually you'll want to get better at it (ie. what they call lame-man modelling aka Oslo in .NET).

无论如何,你最好的机会不是C ++,或C#。它是代码生成,即。比现代C ++'模板'推动更*的元编程..你会发现它类似于JSON数组注释,可以使用精神或(我的建议是)滚动你自己的工具。从长远来看,它有所帮助,最终你会想要更好地完成它(即他们称之为蹩脚的人造型,即.NET中的奥斯陆)。

[ problems like that are all over many languages, its a drawback of all C-style ones ( C, C++, Java, C#, you name it); very similar to arrays of arrays hackery required for any type of cross-domain or semantic I/O work and evident even in web-tech like SOAP etc.. new C++0x variadic bits don't help much here either but apparently can bring exponentially faster compile-times if you chose to play with some template hackery. Who cares :) ]

[像这样的问题遍及许多语言,它是所有C风格的缺点(C,C ++,Java,C#,你的名字);非常类似于任何类型的跨域或语义I / O工作所需的数组hackery,甚至在像SOAP等网络技术中也很明显。新的C ++ 0x可变位在这里也没有多大帮助,但显然可以如果你选择使用一些模板hackery,那么编译时间会快得多。谁在乎 :) ]

#1


The members are actually copy-initialized. The default constructor for each one is not called and no operator= is involved contrary to what some other answers suggest. It can be shown by a software called geordi - alternatively by reading through the Standard. I'll show the "fun" way using that software. It has got a class tracked::B that can show us when constructors/copy-constructors or destructors/copy assignment operators are called. The output it shows is (TRACK limits tracking to the statement following it):

成员实际上是复制初始化的。不调用每个默认构造函数,并且没有涉及operator =,这与其他一些答案所暗示的相反。它可以通过一个名为geordi的软件显示 - 或者通过阅读标准来显示。我将展示使用该软件的“有趣”方式。它有一个跟踪的类:: B,它可以在调用构造函数/复制构造函数或析构函数/复制赋值运算符时向我们显示。它显示的输出是(TRACK限制跟踪它后面的语句):

B1*(B0) B1~

I used this code

我用过这段代码

struct T { tracked::B b; }; int main() { tracked::B b; TRACK T t = { b };  }

As you see, the second B object - which is the member within the local variable t, is copy initialized from the other object b. Of course, no assignment operator is activated. You can read about it in 12.6.1/2 in the Standard, if you wish.

如您所见,第二个B对象 - 它是局部变量t中的成员,是从另一个对象b初始化的副本。当然,没有激活赋值运算符。如果您愿意,可以在标准中的12.6.1 / 2中阅读。

The same, by the way, is true with arrays (which are likewise aggregates). Many people believe that objects that are member of arrays must have a type that has a default constructor. But that's not true. They can just be copy initialized by another object of their type and it will work fine.

顺便说一句,对于数组(同样是聚合)也是如此。许多人认为作为数组成员的对象必须具有具有默认构造函数的类型。但事实并非如此。它们只能由其他类型的对象进行初始化,并且可以正常工作。

All other elements that were not explicitly initialized in the aggregate are value initialized. Value-initialization is a mixture of default initialization and zero initialization. Actually, if a member has a type that has a user declared constructor, then that constructor is invoked. If it has a type that does not have a user declared constructor, then each member of it is value initialized. For built-in types (int, bool, pointers, ...) a value initialization is the same as zero initialization (that means that such a variable will become zero). The following will initialize each member to zero - except the first (a), which will be one:

未在聚合中显式初始化的所有其他元素都是值初始化的。值初始化是默认初始化和零初始化的混合。实际上,如果成员的类型具有用户声明的构造函数,则调用该构造函数。如果它的类型没有用户声明的构造函数,那么它的每个成员都是值初始化的。对于内置类型(int,bool,pointers,...),值初始化与零初始化相同(这意味着这样的变量将变为零)。以下将每个成员初始化为零 - 除了第一个(a),它将是一个:

struct T { int a, b, c; }; int main() { T t = { 1 }; }

Those initialization rules are scary, indeed - especially because the 2003 revision of C++ introduced that value initialization. It wasn't part of the Standard as of 1998. If you are more interested in those brace enclosed initializations, you can read How to initialize nested structures in C++?.

确实,这些初始化规则是可怕的 - 特别是因为2003年版的C ++引入了值初始化。它不是1998年标准的一部分。如果你对那些大括号括起来的初始化更感兴趣,你可以阅读如何在C ++中初始化嵌套结构?

#2


It's not calling the default ctor, as others have written. Conceptually it's the same, but in practice, you'll find no function call in the assembly code.

正如其他人所写的那样,它并没有调用默认的ctor。从概念上讲它是一样的,但在实践中,你会发现汇编代码中没有函数调用。

Instead, the members remain uninitialized; you're initializing them with the curly-brace construct.

相反,成员仍然没有初始化;你是用花括号结构初始化它们的。

Interestingly enough, this:

有趣的是,这个:

PhoneNumber homePhone = {858, 555, 1234};

Results in this assembly (GCC 4.0.1, -O0):

此程序集中的结果(GCC 4.0.1,-O0):

movl  $858, -20(%ebp)
movl  $555, -16(%ebp)
movl  $1234, -12(%ebp)

Not many surprises there. The assembly is inline the function containing the above C++ statement. The values (starting with $) are moved (movl) into offsets into the stack (ebp register). They're negative because the memory locations for the struct members precede the initialization code.

那里没什么惊喜。程序集内联包含上述C ++语句的函数。将值(以$开头)移动(movl)到堆栈中的偏移量(ebp寄存器)。它们是负面的,因为struct成员的内存位置在初始化代码之前。

If you don't fully initialize the struct, i.e. leave out some members like so:

如果你没有完全初始化结构,即省略一些像这样的成员:

PhoneNumber homePhone = {858, 555};

... then I get the following assembly code:

...然后我得到以下汇编代码:

movl  $0, -20(%ebp)
movl  $0, -16(%ebp)
movl  $0, -12(%ebp)
movl  $858, -20(%ebp)
movl  $555, -16(%ebp)

Seems as if the compiler then actually does something very similar to calling the default constructor, followed by assignment. But again, this is inline in the calling function, not a function call.

看起来好像编译器实际上做了一些非常类似于调用默认构造函数的东西,然后是赋值。但同样,这是在调用函数内联,而不是函数调用。

If on the other hand you define a default constructor that initializes the members, to the given values, like so:

另一方面,如果您定义了一个默认构造函数,它将成员初始化为给定值,如下所示:

struct PhoneNumber {
  PhoneNumber()
    : areaCode(858)
    , prefix(555)
    , suffix(1234)
  {
  }

  int areaCode;
  int prefix;
  int suffix;
};

PhoneNumber homePhone;

Then you get assembly code that actually calls a function, and initializes the data members via a pointer to the struct:

然后你获得实际调用函数的汇编代码,并通过指向struct的指针初始化数据成员:

movl  8(%ebp), %eax
movl  $858, (%eax)
movl  8(%ebp), %eax
movl  $555, 4(%eax)
movl  8(%ebp), %eax
movl  $1234, 8(%eax)

Each line that goes movl 8(%ebp), %eax sets the pointer value (eax register) to the beginning of the struct's data. In the other lines, eax is used directly, with an offset of 4 and an offset of 8, similar to the direct stack addressing in the previous two examples.

每个行都是movl 8(%ebp),%eax将指针值(eax寄存器)设置为struct数据的开头。在其他行中,eax直接使用,偏移量为4,偏移量为8,类似于前两个示例中的直接堆栈寻址。

Of course all of this is specific to the compiler implementation, but I'd be surprised if other compilers did something extraordinarily different.

当然所有这些都是编译器实现所特有的,但如果其他编译器做了一些非常不同的事情,我会感到惊讶。

#3


A struct in C++ is like a class. The default constructor is being called. Afterwards, each field is copied with its assignment operator.

C ++中的结构就像一个类。正在调用默认构造函数。然后,使用其赋值运算符复制每个字段。

#4


Initialization is, at least to me, one of the toughest parts of the C++ standard. The syntax you are using: Aggregate x = { 1, 2, 3, 4 }; defines the initialization of an aggregate type with the first four members assigned values 1, 2, 3 and 4.

至少在我看来,初始化是C ++标准中最棘手的部分之一。您正在使用的语法:聚合x = {1,2,3,4};定义聚合类型的初始化,前四个成员分配值1,2,3和4。

As a note to your particular case (the struct has grown from 3 to 4 elements), the fields not present in the initialization list between the curly braces will be value initialized, which in particular for scalar types is equivalent to zero initialization which is itself the same as assigning 0. Thus your fourth element will be initialized to 0.

作为特定情况的注释(结构从3个元素增长到4个元素),花括号之间的初始化列表中不存在的字段将被初始化值,特别是对于标量类型而言,它等同于零初始化,它本身就是零与赋值0相同。因此,您的第四个元素将初始化为0。

References

It is all defined in the C++ standard, chapter 8.5, and more precisely in 8.5.1 Aggregates. Aggregates will not be initialized with any implicitly declared default constructor. If you use the syntax above you are asking the compiler to initialize the given fields with the provided values. Any extra field in the aggregate shall be value initialized

它全部在C ++标准的第8.5章中定义,更确切地说在8.5.1 Aggregates中定义。不会使用任何隐式声明的默认构造函数初始化聚合。如果使用上面的语法,则要求编译器使用提供的值初始化给定字段。聚合中的任何额外字段都应初始化值

Now, value initialization is defined as a call to the user defined default constructor if the type is a class with such constructor. If it is an array or a non-union class without user defined constructor then each one of the member attributes will be value initialized. Otherwise the object will be zero initialized, which then again is defined as...

现在,如果类型是具有此类构造函数的类,则值初始化定义为对用户定义的默认构造函数的调用。如果它是没有用户定义构造函数的数组或非联合类,则每个成员属性都将被初始化值。否则,对象将初始化为零,然后再次定义为...

Zero initialization is defined as setting the value to 0 for scalar types. For classes each class data member and base class will be zero initialized. For unions, the first member (only) will be zero initialized, for arrays all members will be zero initialized.

零初始化定义为将标量类型的值设置为0。对于类,每个类的数据成员和基类将初始化为零。对于联合,第一个成员(仅)将初始化为零,对于数组,所有成员将初始化为零。

#5


It's effectively calling the default ctor; what's happening is a struct is allocated, and each value is assigned used default "=".

它有效地调用了默认的ctor;发生了什么是分配结构,并为每个值分配使用默认值“=”。

#6


However, I have hundreds of these PhoneNumber instances already created with only 3 fields (xxx, xxx, xxxx). So I don't want to go through and modify EVERY single instantiation of my PhoneNumber object that is already defined.

但是,我已经创建了数百个这样的PhoneNumber实例,只有3个字段(xxx,xxx,xxxx)。因此,我不想通过修改已定义的PhoneNumber对象的每个单一实例化。

No problem, you just call update-instance-for-redefined-class and ..... er, nevermind. Proceed to mark this "unhelpful"

没问题,你只需要调用update-instance-for-redefined-class和.....呃,没关系。继续标记这个“无益”

#7


There is no constructor on your type involved, so the existing three-parameter syntax would need to be modified at aggregate initialisation site.

您的类型没有构造函数,因此需要在聚合初始化站点修改现有的三参数语法。

Unless semantics of your newly added field ie. that new field type, are 'zeroed design-aware' ( idiom recommended by .NET programming, Brad and Co etc in design guidelines nonsense), you

除非您新添加的字段的语义,即。新的字段类型,'归零设计意识'(.NET编程推荐的成语,Brad和Co等在设计指南中无意义),你

cannot :

a) provide something more meaningful as either C++ default parameters if with some magic there was a method involved ( deault/optional params soon to be available in mass-market C# shop near the grocers web 4.0 and for old COM )

a)提供一些更有意义的东西作为C ++默认参数,如果有一些魔法有一个方法涉及(deault / optional params很快就可以在杂货店web 4.0附近的大众市场C#商店和旧COM中使用)

nor can you

你也不是吗?

b) follow the C# like pattern of designing value types with invalid value markers as 0s ( which is in this case arguably very bad and bad in general if you do not have control over the constants - something source-level libraries do very well and all-JavaTM MS -like frameworks suck at ).

b)遵循C#类似设计值类型的模式,将无效值标记设置为0(在这种情况下,如果您无法控制常量,这通常会非常糟糕和糟糕 - 某些源级库非常好并且所有-JavaTM类似于MS的框架很糟糕。

In short, if 0 is a valid value you are stuffed and something most compiler writers saw as useful before any managed style or idiom ever existed; but it isn't necessarily right.

简而言之,如果0是有效值,那么大多数编译器编写者在任何托管样式或习惯用法存在之前都认为它是有用的;但它不一定是对的。

Anyway, you best chance isn't C++, or C#. It is code-generation, ie. more liberal meta-programming than modern C++ 'templating' pushes on.. You'll find it similar to JSON array annotation and could use either spirit or (my advice would be) roll your own utils. It helps in the long run, and eventually you'll want to get better at it (ie. what they call lame-man modelling aka Oslo in .NET).

无论如何,你最好的机会不是C ++,或C#。它是代码生成,即。比现代C ++'模板'推动更*的元编程..你会发现它类似于JSON数组注释,可以使用精神或(我的建议是)滚动你自己的工具。从长远来看,它有所帮助,最终你会想要更好地完成它(即他们称之为蹩脚的人造型,即.NET中的奥斯陆)。

[ problems like that are all over many languages, its a drawback of all C-style ones ( C, C++, Java, C#, you name it); very similar to arrays of arrays hackery required for any type of cross-domain or semantic I/O work and evident even in web-tech like SOAP etc.. new C++0x variadic bits don't help much here either but apparently can bring exponentially faster compile-times if you chose to play with some template hackery. Who cares :) ]

[像这样的问题遍及许多语言,它是所有C风格的缺点(C,C ++,Java,C#,你的名字);非常类似于任何类型的跨域或语义I / O工作所需的数组hackery,甚至在像SOAP等网络技术中也很明显。新的C ++ 0x可变位在这里也没有多大帮助,但显然可以如果你选择使用一些模板hackery,那么编译时间会快得多。谁在乎 :) ]