值类型的分配

时间:2014-04-10 13:01:22

标签: c# .net clr value-type

当您将值类型的实例分配给另一个实例时,该对象将逐位复制到目标位置:

private struct Word
{
    public Word(char c) { ... }
}

public void Method(Word a)
{
    Word b = a; //a is copied and stored in b
}

但是给出了以下代码:

private Word _word;

public void Method() {
    _word = new Word('x');
}

我怀疑首先评估右侧(RHS)表达式 - 它实例化堆栈上的值类型 - 然后然后将值复制并存储在{{的位置上1}}字段,位于堆上。

另一种方法是考虑左侧,并直接在_word上实例化值类型,避免复制对象。

我的怀疑是否正确?如果是,我想可以安全地假设第一个代码块比第二个代码块表现更好。

_word

注意:我不打算对任何事情进行微观优化。

编辑:我的问题的核心是,正如李所说:结构是直接分配到的,还是需要分配然后复制?

2 个答案:

答案 0 :(得分:9)

  

当您将值类型的实例分配给另一个实例时,该对象将逐位复制到目标位置

将值类型的实例分配给相同类型的变量时,该值将复制到目标位置,是。但对于引用类型也是如此:引用被逐位复制到目标位置。 指示物当然保持在原地。

  

我怀疑首先评估右侧(RHS)表达式

规范声明左侧被评估以产生变量,然后评估右侧产生一个值,然后进行赋值。

在示例中,您给左侧的评估不会产生可观察到的副作用,因此它的评估可以由C#编译器中的优化器,抖动或CPU重新排序,如果其中任何一个选择的话。但如果你有像

这样的东西
x[i++] = v();

然后左手边的副作用必须在右手边的呼叫之前发生。

  

我的问题的核心是:结构是直接分配的,还是需要分配然后复制?

规范声明结构分配在临时位置 - 通常是堆栈或实际中的寄存器 - 然后复制到它们的最终目的地。然而,在某些情况下,优化器可以确定用户不可能注意到突变是否在最终目的地“就地”发生。这是 copy elision 优化,如果C#编译器感觉它可以逃脱它,它将执行此优化。

有关详细信息,请参阅我关于此主题的文章:

http://ericlippert.com/2010/10/11/debunking-another-myth-about-value-types/

答案 1 :(得分:0)

是首选吗?

多个相同结构的商业案例是什么?
如果你需要多个相同的对象,那么结构是最好的选择吗?

以这种方式初始化的struct(re)可能不是示例用例的良好解决方案 在新阵列中,使用默认ctor(无ctor)分配和初始化WordStruct 您没有选择使用另一个ctor初始化结构数组 如果你确实需要相同的结构,那么这将是首选

WordStruct[] WordStructS = new WordStruct[1000];
for (int i = 0; i < WordStructS.Length; i++) { WordStructS[i].C = 'x'; }

如果你真正需要做多个相同的对象,那么考虑一个班级 分配了一个新的数组,但尚未初始化 您不会浪费使用默认构造函数初始化的资源

WordClass[] WordClassS = new WordClass[1000];
for (int i = 0; i < WordClassS.Length; i++) { WordClassS[i] = new WordClass('x'); }

如果要概括对象(结构或类)的深层副本,请考虑IConable
在结构的情况下,我怀疑它比有点明智的副本更有效(但我不是正面的) 在类的情况下,它将使克隆(深拷贝)而不是参考

public struct WordStruct : ICloneable 
{
    public char C;
    public WordStruct(char C) 
    {
        this.C = C;
    }
    public object Clone()
    {
        WordStruct newWordStruct = (WordStruct)this.MemberwiseClone();
        return newWordStruct;
    }
}

我在评论中说你好奇,但在问题中不明确 在问题中,您说第一个代码块优先于第二个代码

我知道这是一个有趣的好奇心问题 但如果仅仅是好奇心,那么这个问题就应该停止了 我的怀疑是否正确?