C++ 如何一次将多个值分配给一个结构?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9269825/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to assign multiple values into a struct at once?
提问by jim
I can do this on initialization for a struct Foo:
我可以在 struct Foo 的初始化时执行此操作:
Foo foo = {bunch, of, things, initialized};
but, I can't do this:
但是,我不能这样做:
Foo foo;
foo = {bunch, of, things, initialized};
So, two questions:
所以,两个问题:
- Why can't I do the latter, is the former a special constructor for initialization only?
How can I do something similar to the second example, i.e. declare a bunch of variables for a struct in a single line of code after it's already been initialized? I'm trying to avoid having to do this for large structs with many variables:
Foo foo; foo.a = 1; foo.b = 2; foo.c = 3; //... ad infinitum
- 为什么我不能做后者,前者是仅用于初始化的特殊构造函数吗?
我该如何做类似于第二个例子的事情,即在一个结构体已经被初始化之后,在一行代码中为它声明一堆变量?我试图避免对具有许多变量的大型结构执行此操作:
Foo foo; foo.a = 1; foo.b = 2; foo.c = 3; //... ad infinitum
采纳答案by John Humphreys - w00te
The first is an aggregate initializer - you can read up on those and tagged initializers at this solution:
第一个是聚合初始值设定项 - 您可以在此解决方案中阅读这些和标记初始值设定项:
What is tagged structure initialization syntax?
It is a special initialization syntax, and you can't do something similar after initialization of your struct. What you can do is provide a member (or non-member) function to take your series of values as parameters which you then assign within the member function - that would allow you to accomplish this after the structure is initialized in a way that is equally concise (after you've written the function the first time of course!)
这是一种特殊的初始化语法,在结构体初始化之后你不能做类似的事情。您可以做的是提供一个成员(或非成员)函数来将您的一系列值作为参数,然后您在成员函数中分配这些参数 - 这将允许您在结构以同样的方式初始化后完成此操作简洁(当然是在您第一次编写函数之后!)
回答by David Grayson
Try this:
尝试这个:
Foo foo;
foo = (Foo){bunch, of, things, initialized};
This will work if you have a good compiler (e.g. GCC). You might need to turn on C99 mode with --std=gnu99
, I'm not sure.
如果您有一个好的编译器(例如 GCC),这将起作用。您可能需要使用 开启 C99 模式--std=gnu99
,我不确定。
回答by Nikos Athanasiou
In C++11 you can perform multiple assignment with "tie" (declared in the tuple header)
在 C++11 中,您可以使用“tie”(在元组头中声明)执行多重赋值
struct foo {
int a, b, c;
} f;
std::tie(f.a, f.b, f.c) = std::make_tuple(1, 2, 3);
If your right hand expression is of fixed size and you only need to get some of the elements, you can use the ignore placeholder with tie
如果你的右手表达式是固定大小的并且你只需要获取一些元素,你可以使用忽略占位符和领带
std::tie(std::ignore, f.b, std::ignore) = some_tuple; // only f.b modified
If you find the syntax std::tie(f.a, f.b, f.c) too code cluttering you could have a member function returning that tuple of references
如果你发现语法 std::tie(fa, fb, fc) 太代码混乱,你可以有一个成员函数返回该引用元组
struct foo {
int a, b, c;
auto members() -> decltype(std::tie(a, b, c)) {
return std::tie(a, b, c);
}
} f;
f.members() = std::make_tuple(1, 2, 3);
All this ofcourse assuming that overloading the assignment operator is not an option because your struct is not constructible by such sequence of values, in which case you could say
所有这些当然都假设重载赋值运算符不是一种选择,因为您的结构不能由这样的值序列构造,在这种情况下,您可以说
f = foo(1, 2, 3);
回答by J-Dizzle
Memory Footprint- Here is an interesting i386 addition.
内存占用- 这是一个有趣的 i386 补充。
After much hassle, using optimizationand memcpyseems to generate the smallest footprint using i386 with GCC and C99. I am using -O3 here. stdlib seems to have all sorts of fun compiler optimizations at hand, and this example makes use of that (memcpy is actually compiled out here).
经过一番折腾,使用优化和memcpy似乎使用带有 GCC 和 C99 的 i386 生成最小的占用空间。我在这里使用 -O3。stdlib 似乎手头有各种有趣的编译器优化,这个例子利用了它(memcpy 实际上是在这里编译出来的)。
Do this by:
这样做:
Foo foo; //some global variable
void setStructVal (void) {
const Foo FOO_ASSIGN_VAL = { //this goes into .rodata
.bunch = 1,
.of = 2,
.things = 3,
.initialized = 4
};
memcpy((void*) &FOO_ASSIGN_VAL, (void*) foo, sizeof(Foo));
return;
}
Result:
结果:
- (.rodata) FOO_ASSIGN_VAL is stored in .rodata
- (.text) a sequence of *movl FOO_ASSIGN_VAL, %registers* occur
- (.text) a sequence of movl %registers, foooccur
- (.rodata) FOO_ASSIGN_VAL 存储在 .rodata
- (.text) 一系列 *movl FOO_ASSIGN_VAL, %registers* 发生
- (.text) 一系列movl %registers, foo发生
Example:
例子:
Say Foo was a 48 field struct of uint8_t values. It is aligned in memory.
(IDEAL) On a 32-bit machine, this COULDbe as quick as 12 MOVL instructions of immediates out to foo's address space. For me this is 12*10 == 120bytes of .text in size.
(ACTUAL) However, using the answer by AUTO will likely generate 48 MOVB instructions in .text. For me this is 48*7 == 336bytes of .text!!
(SMALLEST*) Use the memcpy version above. IF alignment is taken care of,
- FOO_ASSIGN_VAL is placed in .rodata (48 bytes),
- 12 MOVL into %register
- 12 MOVL outof %registers are used in .text (24*10) == 240bytes.
- For me then this is a total of 288 bytes.
说 Foo 是一个 48 字段的 uint8_t 值结构。它在内存中对齐。
(IDEAL)在32位机,该COULD是立即数的那么快,12 MOVL指令出为foo的地址空间。对我来说,这是 12*10 == 120 字节的 .text 大小。
(实际) 但是,使用 AUTO 的答案可能会在 .text 中生成 48 条 MOVB 指令。对我来说,这是 48*7 == 336 字节的 .text !!
( SMALLEST*) 使用上面的 memcpy 版本。IF对齐得到照顾,
- FOO_ASSIGN_VAL 放在 .rodata(48 字节)中,
- 12 MOVL 进入 %register
- 在 .text (24*10) == 240bytes 中使用了 12 个 MOVL outof %registers。
- 对我来说,这总共是 288 个字节。
So, for me at least with my i386 code,
所以,至少对我来说,我的 i386 代码,
- Ideal: 120 bytes
- Direct: 336 bytes
- Smallest: 288 bytes
*Smallest here means 'smallest footprint I know of'. It also executes faster than the above methods (24 instructions vs 48). Of course, the IDEAL version is fastest & smallest, but I still can't figure that out.
*这里最小的意思是“我所知道的最小的足迹”。它还比上述方法执行得更快(24 条指令 vs 48 条)。当然,IDEAL 版本是最快和最小的,但我仍然无法弄清楚。
-Justin
-贾斯汀
*Does anyone know how to get implementation of 'IDEAL' above? It is annoying the hell out of me!!
*有谁知道如何实现上面的“ IDEAL”?真是烦死我了!!
回答by Codesmith
If you don't care too much about efficiency, you could double assign: i.e. create a new instance of the structure using aggregate initialization, and then copy it over:
如果你不太关心效率,你可以双重分配:即使用聚合初始化创建一个新的结构实例,然后复制它:
struct Foo foo; { struct Foo __tmp__ = {bunch, of, things, initialized}; foo = __tmp__; }
Make sure you keep the portion wrapped in {}s so as to discard the unnecessary temporary variable as soon as it's no longer necessary.
确保将部分保留在 {} 中,以便在不再需要时立即丢弃不必要的临时变量。
Note this isn't as efficient as making, e.g., a 'set' function in the struct (if c++) or out of the struct, accepting a struct pointer (if C). But if you need a quick, preferably temporary, alternative to writing element-by-element assignment, this might do.
请注意,这不如在结构中(如果是 c++)或在结构外制作一个“set”函数,接受结构指针(如果是 C)那么有效。但是,如果您需要一个快速的、最好是临时的替代方法来编写逐个元素的赋值,这可能是可行的。
回答by Simon
If you care about efficiency, you can define a union of the same length as your structure, with a type you can assign at once.
如果您关心效率,您可以定义一个与您的结构长度相同的联合,您可以立即分配一个类型。
To assign values by elements use the struct of your union, to assign the whole data, use the other type of your union.
要按元素分配值,请使用联合的结构,要分配整个数据,请使用其他类型的联合。
typedef union
{
struct
{
char a;
char b;
} Foo;
unsigned int whole;
} MyUnion;
MyUnion _Union;
_Union.Foo.a = 0x23; // assign by element
_Union.Foo.b = 0x45; // assign by element
_Union.whole = 0x6789; // assign at once
Be carefull about your memory organization (is "a" the MSB or the LSB of "whole"?).
请注意您的内存组织(“a”是“整体”的 MSB 还是 LSB?)。