The reft operation of '&' is a garbage value

本文介绍了如何通过初始化未使用的数组来解决Xcode静态分析工具报告的潜在脏数据警告。通过对示例代码进行分析,展示了如何正确初始化变量以避免此类警告。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



这个警告应该是xcode的静态分析的警告。
先看看百度翻译对garbage的翻译 垃圾; 脏东西; 丢弃的食物; 无用的数据
也就是说这个被警告的变量里面有脏数据,比如使用未初始化的数组(inbuf[4]

unsigned char inbuf[4];

unsigned char outbuf[3] = {0,0, 0};


outbuf [0] = ( inbuf[0] <<2 ) | ( ( inbuf[1] &0x30) >> 4 );

outbuf [1] = ( ( inbuf[1] &0x0F ) << 4 ) | ( ( inbuf[2] &0x3C ) >> 2 );

outbuf [2] = ( ( inbuf[2] &0x03 ) << 6 ) | ( inbuf[3] &0x3F );

anlayze一下,是不是有警告!

修改,只需要对inbuf[4]初始化一下:

unsigned char inbuf[4] = {000, 0};

在看看,没有警告了吧



//---------------------------------------------- // NGUI: Next-Gen UI kit // Copyright © 2011-2015 Tasharen Entertainment //---------------------------------------------- using UnityEngine; using System.Collections.Generic; /// <summary> /// UI Panel is responsible for collecting, sorting and updating widgets in addition to generating widgets' geometry. /// </summary> [ExecuteInEditMode] [AddComponentMenu("NGUI/UI/NGUI Panel")] public class UIPanel : UIRect { /// <summary> /// List of active panels. /// </summary> static public List<UIPanel> list = new List<UIPanel>(); public enum RenderQueue { Automatic, StartAt, Explicit, } public delegate void OnGeometryUpdated (); /// <summary> /// Notification triggered when the panel's geometry get rebuilt. It's mainly here for debugging purposes. /// </summary> public OnGeometryUpdated onGeometryUpdated; /// <summary> /// Whether this panel will show up in the panel tool (set this to 'false' for dynamically created temporary panels) /// </summary> public bool showInPanelTool = true; /// <summary> /// Whether normals and tangents will be generated for all meshes /// </summary> public bool generateNormals = false; /// <summary> /// Whether widgets drawn by this panel are static (won't move). This will improve performance. /// </summary> public bool widgetsAreStatic = false; /// <summary> /// Whether widgets will be culled while the panel is being dragged. /// Having this on improves performance, but turning it off will reduce garbage collection. /// </summary> public bool cullWhileDragging = true; /// <summary> /// Optimization flag. Makes the assumption that the panel's geometry /// will always be on screen and the bounds don't need to be re-calculated. /// </summary> public bool alwaysOnScreen = false; /// <summary> /// By default, non-clipped panels use the camera's bounds, and the panel's position has no effect. /// If you want the panel's position to actually be used with anchors, set this field to 'true'. /// </summary> public bool anchorOffset = false; /// <summary> /// Whether the soft border will be used as padding. /// </summary> public bool softBorderPadding = true; /// <summary> /// By default all panels manage render queues of their draw calls themselves by incrementing them /// so that the geometry is drawn in the proper order. You can alter this behaviour. /// </summary> public RenderQueue renderQueue = RenderQueue.Automatic; /// <summary> /// Render queue used by the panel. The default value of '3000' is the equivalent of "Transparent". /// This property is only used if 'renderQueue' is set to something other than "Automatic". /// </summary> public int startingRenderQueue = 3000; /// <summary> /// List of widgets managed by this panel. Do not attempt to modify this list yourself. /// </summary> [System.NonSerialized] public List<UIWidget> widgets = new List<UIWidget>(); /// <summary> /// List of draw calls created by this panel. Do not attempt to modify this list yourself. /// </summary> [System.NonSerialized] public List<UIDrawCall> drawCalls = new List<UIDrawCall>(); /// <summary> /// Matrix that will transform the specified world coordinates to relative-to-panel coordinates. /// </summary> [System.NonSerialized] public Matrix4x4 worldToLocal = Matrix4x4.identity; /// <summary> /// Cached clip range passed to the draw call's shader. /// </summary> [System.NonSerialized] public Vector4 drawCallClipRange = new Vector4(0f, 0f, 1f, 1f); public delegate void OnClippingMoved (UIPanel panel); /// <summary> /// Event callback that's triggered when the panel's clip region gets moved. /// </summary> public OnClippingMoved onClipMove; // Clip texture feature contributed by the community: http://www.tasharen.com/forum/index.php?topic=9268.0 [HideInInspector][SerializeField] Texture2D mClipTexture = null; // Panel's alpha (affects the alpha of all widgets) [HideInInspector][SerializeField] float mAlpha = 1f; // Clipping rectangle [HideInInspector][SerializeField] UIDrawCall.Clipping mClipping = UIDrawCall.Clipping.None; [HideInInspector][SerializeField] Vector4 mClipRange = new Vector4(0f, 0f, 300f, 200f); [HideInInspector][SerializeField] Vector2 mClipSoftness = new Vector2(4f, 4f); [HideInInspector][SerializeField] int mDepth = 0; [HideInInspector][SerializeField] int mSortingOrder = 0; // Whether a full rebuild of geometry buffers is required bool mRebuild = false; bool mResized = false; [SerializeField] Vector2 mClipOffset = Vector2.zero; float mCullTime = 0f; float mUpdateTime = 0f; int mMatrixFrame = -1; int mAlphaFrameID = 0; int mLayer = -1; // Values used for visibility checks static float[] mTemp = new float[4]; Vector2 mMin = Vector2.zero; Vector2 mMax = Vector2.zero; bool mHalfPixelOffset = false; bool mSortWidgets = false; bool mUpdateScroll = false; /// <summary> /// Helper property that returns the first unused depth value. /// </summary> static public int nextUnusedDepth { get { int highest = int.MinValue; for (int i = 0, imax = list.Count; i < imax; ++i) highest = Mathf.Max(highest, list[i].depth); return (highest == int.MinValue) ? 0 : highest + 1; } } /// <summary> /// Whether the rectangle can be anchored. /// </summary> public override bool canBeAnchored { get { return mClipping != UIDrawCall.Clipping.None; } } /// <summary> /// Panel's alpha affects everything drawn by the panel. /// </summary> public override float alpha { get { return mAlpha; } set { float val = Mathf.Clamp01(value); if (mAlpha != val) { mAlphaFrameID = -1; mResized = true; mAlpha = val; SetDirty(); } } } /// <summary> /// Panels can have their own depth value that will change the order with which everything they manage gets drawn. /// </summary> public int depth { get { return mDepth; } set { if (mDepth != value) { mDepth = value; #if UNITY_EDITOR NGUITools.SetDirty(this); #endif list.Sort(CompareFunc); } } } /// <summary> /// Sorting order value for the panel's draw calls, to be used with Unity's 2D system. /// </summary> public int sortingOrder { get { return mSortingOrder; } set { if (mSortingOrder != value) { mSortingOrder = value; #if UNITY_EDITOR NGUITools.SetDirty(this); #endif UpdateDrawCalls(); } } } /// <summary> /// Function that can be used to depth-sort panels. /// </summary> static public int CompareFunc (UIPanel a, UIPanel b) { if (a != b && a != null && b != null) { if (a.mDepth < b.mDepth) return -1; if (a.mDepth > b.mDepth) return 1; return (a.GetInstanceID() < b.GetInstanceID()) ? -1 : 1; } return 0; } /// <summary> /// Panel's width in pixels. /// </summary> public float width { get { return GetViewSize().x; } } /// <summary> /// Panel's height in pixels. /// </summary> public float height { get { return GetViewSize().y; } } /// <summary> /// Whether the panel's drawn geometry needs to be offset by a half-pixel. /// </summary> public bool halfPixelOffset { get { return mHalfPixelOffset; } } /// <summary> /// Whether the camera is used to draw UI geometry. /// </summary> #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 public bool usedForUI { get { return (anchorCamera != null && mCam.isOrthoGraphic); } } #else public bool usedForUI { get { return (anchorCamera != null && mCam.orthographic); } } #endif /// <summary> /// Directx9 pixel offset, used for drawing. /// </summary> public Vector3 drawCallOffset { get { #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 if (anchorCamera != null && mCam.isOrthoGraphic) #else if (anchorCamera != null && mCam.orthographic) #endif { Vector2 size = GetWindowSize(); float pixelSize = (root != null) ? root.pixelSizeAdjustment : 1f; float mod = (pixelSize / size.y) / mCam.orthographicSize; bool x = mHalfPixelOffset; bool y = mHalfPixelOffset; if ((Mathf.RoundToInt(size.x) & 1) == 1) x = !x; if ((Mathf.RoundToInt(size.y) & 1) == 1) y = !y; return new Vector3(x ? -mod : 0f, y ? mod : 0f); } return Vector3.zero; } } /// <summary> /// Clipping method used by all draw calls. /// </summary> public UIDrawCall.Clipping clipping { get { return mClipping; } set { if (mClipping != value) { mResized = true; mClipping = value; mMatrixFrame = -1; #if UNITY_EDITOR if (!Application.isPlaying) UpdateDrawCalls(); #endif } } } UIPanel mParentPanel = null; /// <summary> /// Reference to the parent panel, if any. /// </summary> public UIPanel parentPanel { get { return mParentPanel; } } /// <summary> /// Number of times the panel's contents get clipped. /// </summary> public int clipCount { get { int count = 0; UIPanel p = this; while (p != null) { if (p.mClipping == UIDrawCall.Clipping.SoftClip || p.mClipping == UIDrawCall.Clipping.TextureMask) ++count; p = p.mParentPanel; } return count; } } /// <summary> /// Whether the panel will actually perform clipping of children. /// </summary> public bool hasClipping { get { return mClipping == UIDrawCall.Clipping.SoftClip || mClipping == UIDrawCall.Clipping.TextureMask; } } /// <summary> /// Whether the panel will actually perform clipping of children. /// </summary> public bool hasCumulativeClipping { get { return clipCount != 0; } } [System.Obsolete("Use 'hasClipping' or 'hasCumulativeClipping' instead")] public bool clipsChildren { get { return hasCumulativeClipping; } } /// <summary> /// Clipping area offset used to make it possible to move clipped panels (scroll views) efficiently. /// Scroll views move by adjusting the clip offset by one value, and the transform position by the inverse. /// This makes it possible to not have to rebuild the geometry, greatly improving performance. /// </summary> public Vector2 clipOffset { get { return mClipOffset; } set { if (Mathf.Abs(mClipOffset.x - value.x) > 0.001f || Mathf.Abs(mClipOffset.y - value.y) > 0.001f) { mClipOffset = value; InvalidateClipping(); // Call the event delegate if (onClipMove != null) onClipMove(this); #if UNITY_EDITOR if (!Application.isPlaying) UpdateDrawCalls(); #endif } } } /// <summary> /// Invalidate the panel's clipping, calling child panels in turn. /// </summary> void InvalidateClipping () { mResized = true; mMatrixFrame = -1; mCullTime = (mCullTime == 0f) ? 0.001f : RealTime.time + 0.15f; for (int i = 0, imax = list.Count; i < imax; ++i) { UIPanel p = list[i]; if (p != this && p.parentPanel == this) p.InvalidateClipping(); } } /// <summary> /// Texture used to clip the region. /// </summary> public Texture2D clipTexture { get { return mClipTexture; } set { if (mClipTexture != value) { mClipTexture = value; #if UNITY_EDITOR if (!Application.isPlaying) UpdateDrawCalls(); #endif } } } /// <summary> /// Clipping position (XY) and size (ZW). /// Note that you should not be modifying this property at run-time to reposition the clipping. Adjust clipOffset instead. /// </summary> [System.Obsolete("Use 'finalClipRegion' or 'baseClipRegion' instead")] public Vector4 clipRange { get { return baseClipRegion; } set { baseClipRegion = value; } } /// <summary> /// Clipping position (XY) and size (ZW). /// Note that you should not be modifying this property at run-time to reposition the clipping. Adjust clipOffset instead. /// </summary> public Vector4 baseClipRegion { get { return mClipRange; } set { if (Mathf.Abs(mClipRange.x - value.x) > 0.001f || Mathf.Abs(mClipRange.y - value.y) > 0.001f || Mathf.Abs(mClipRange.z - value.z) > 0.001f || Mathf.Abs(mClipRange.w - value.w) > 0.001f) { mResized = true; mCullTime = (mCullTime == 0f) ? 0.001f : RealTime.time + 0.15f; mClipRange = value; mMatrixFrame = -1; UIScrollView sv = GetComponent<UIScrollView>(); if (sv != null) sv.UpdatePosition(); if (onClipMove != null) onClipMove(this); #if UNITY_EDITOR if (!Application.isPlaying) UpdateDrawCalls(); #endif } } } /// <summary> /// Final clipping region after the offset has been taken into consideration. XY = center, ZW = size. /// </summary> public Vector4 finalClipRegion { get { Vector2 size = GetViewSize(); if (mClipping != UIDrawCall.Clipping.None) { return new Vector4(mClipRange.x + mClipOffset.x, mClipRange.y + mClipOffset.y, size.x, size.y); } return new Vector4(0f, 0f, size.x, size.y); } } /// <summary> /// Clipping softness is used if the clipped style is set to "Soft". /// </summary> public Vector2 clipSoftness { get { return mClipSoftness; } set { if (mClipSoftness != value) { mClipSoftness = value; #if UNITY_EDITOR if (!Application.isPlaying) UpdateDrawCalls(); #endif } } } // Temporary variable to avoid GC allocation static Vector3[] mCorners = new Vector3[4]; /// <summary> /// Local-space corners of the panel's clipping rectangle. The order is bottom-left, top-left, top-right, bottom-right. /// </summary> public override Vector3[] localCorners { get { if (mClipping == UIDrawCall.Clipping.None) { Vector3[] corners = worldCorners; Transform wt = cachedTransform; for (int i = 0; i < 4; ++i) corners[i] = wt.InverseTransformPoint(corners[i]); return corners; } else { float x0 = mClipOffset.x + mClipRange.x - 0.5f * mClipRange.z; float y0 = mClipOffset.y + mClipRange.y - 0.5f * mClipRange.w; float x1 = x0 + mClipRange.z; float y1 = y0 + mClipRange.w; mCorners[0] = new Vector3(x0, y0); mCorners[1] = new Vector3(x0, y1); mCorners[2] = new Vector3(x1, y1); mCorners[3] = new Vector3(x1, y0); } return mCorners; } } /// <summary> /// World-space corners of the panel's clipping rectangle. The order is bottom-left, top-left, top-right, bottom-right. /// </summary> public override Vector3[] worldCorners { get { if (mClipping != UIDrawCall.Clipping.None) { float x0 = mClipOffset.x + mClipRange.x - 0.5f * mClipRange.z; float y0 = mClipOffset.y + mClipRange.y - 0.5f * mClipRange.w; float x1 = x0 + mClipRange.z; float y1 = y0 + mClipRange.w; Transform wt = cachedTransform; mCorners[0] = wt.TransformPoint(x0, y0, 0f); mCorners[1] = wt.TransformPoint(x0, y1, 0f); mCorners[2] = wt.TransformPoint(x1, y1, 0f); mCorners[3] = wt.TransformPoint(x1, y0, 0f); } else if (anchorCamera != null) { Vector3[] corners = mCam.GetWorldCorners(cameraRayDistance); //if (anchorOffset && (mCam == null || mCam.transform.parent != cachedTransform)) //{ // Vector3 off = cachedTransform.position; // for (int i = 0; i < 4; ++i) // corners[i] += off; //} return corners; } else { Vector2 size = GetViewSize(); float x0 = -0.5f * size.x; float y0 = -0.5f * size.y; float x1 = x0 + size.x; float y1 = y0 + size.y; mCorners[0] = new Vector3(x0, y0); mCorners[1] = new Vector3(x0, y1); mCorners[2] = new Vector3(x1, y1); mCorners[3] = new Vector3(x1, y0); if (anchorOffset && (mCam == null || mCam.transform.parent != cachedTransform)) { Vector3 off = cachedTransform.position; for (int i = 0; i < 4; ++i) mCorners[i] += off; } } return mCorners; } } /// <summary> /// Get the sides of the rectangle relative to the specified transform. /// The order is left, top, right, bottom. /// </summary> public override Vector3[] GetSides (Transform relativeTo) { if (mClipping != UIDrawCall.Clipping.None) { float x0 = mClipOffset.x + mClipRange.x - 0.5f * mClipRange.z; float y0 = mClipOffset.y + mClipRange.y - 0.5f * mClipRange.w; float x1 = x0 + mClipRange.z; float y1 = y0 + mClipRange.w; float hx = (x0 + x1) * 0.5f; float hy = (y0 + y1) * 0.5f; Transform wt = cachedTransform; mSides[0] = wt.TransformPoint(x0, hy, 0f); mSides[1] = wt.TransformPoint(hx, y1, 0f); mSides[2] = wt.TransformPoint(x1, hy, 0f); mSides[3] = wt.TransformPoint(hx, y0, 0f); if (relativeTo != null) { for (int i = 0; i < 4; ++i) mSides[i] = relativeTo.InverseTransformPoint(mSides[i]); } return mSides; } else if (anchorCamera != null && anchorOffset) { Vector3[] sides = mCam.GetSides(cameraRayDistance); Vector3 off = cachedTransform.position; for (int i = 0; i < 4; ++i) sides[i] += off; if (relativeTo != null) { for (int i = 0; i < 4; ++i) sides[i] = relativeTo.InverseTransformPoint(sides[i]); } return sides; } return base.GetSides(relativeTo); } /// <summary> /// Invalidating the panel should reset its alpha. /// </summary> public override void Invalidate (bool includeChildren) { mAlphaFrameID = -1; base.Invalidate(includeChildren); } /// <summary> /// Widget's final alpha, after taking the panel's alpha into account. /// </summary> public override float CalculateFinalAlpha (int frameID) { #if UNITY_EDITOR if (mAlphaFrameID != frameID || !Application.isPlaying) #else if (mAlphaFrameID != frameID) #endif { mAlphaFrameID = frameID; UIRect pt = parent; finalAlpha = (parent != null) ? pt.CalculateFinalAlpha(frameID) * mAlpha : mAlpha; } return finalAlpha; } /// <summary> /// Set the panel's rectangle. /// </summary> public override void SetRect (float x, float y, float width, float height) { int finalWidth = Mathf.FloorToInt(width + 0.5f); int finalHeight = Mathf.FloorToInt(height + 0.5f); finalWidth = ((finalWidth >> 1) << 1); finalHeight = ((finalHeight >> 1) << 1); Transform t = cachedTransform; Vector3 pos = t.localPosition; pos.x = Mathf.Floor(x + 0.5f); pos.y = Mathf.Floor(y + 0.5f); if (finalWidth < 2) finalWidth = 2; if (finalHeight < 2) finalHeight = 2; baseClipRegion = new Vector4(pos.x, pos.y, finalWidth, finalHeight); if (isAnchored) { t = t.parent; if (leftAnchor.target) leftAnchor.SetHorizontal(t, x); if (rightAnchor.target) rightAnchor.SetHorizontal(t, x + width); if (bottomAnchor.target) bottomAnchor.SetVertical(t, y); if (topAnchor.target) topAnchor.SetVertical(t, y + height); #if UNITY_EDITOR NGUITools.SetDirty(this); #endif } } /// <summary> /// Returns whether the specified rectangle is visible by the panel. The coordinates must be in world space. /// </summary> #if UNITY_FLASH public bool IsVisible (Vector3 aa, Vector3 bb, Vector3 cc, Vector3 dd) #else public bool IsVisible (Vector3 a, Vector3 b, Vector3 c, Vector3 d) #endif { UpdateTransformMatrix(); // Transform the specified points from world space to local space #if UNITY_FLASH // http://www.tasharen.com/forum/index.php?topic=11390.0 Vector3 a = worldToLocal.MultiplyPoint3x4(aa); Vector3 b = worldToLocal.MultiplyPoint3x4(bb); Vector3 c = worldToLocal.MultiplyPoint3x4(cc); Vector3 d = worldToLocal.MultiplyPoint3x4(dd); #else a = worldToLocal.MultiplyPoint3x4(a); b = worldToLocal.MultiplyPoint3x4(b); c = worldToLocal.MultiplyPoint3x4(c); d = worldToLocal.MultiplyPoint3x4(d); #endif mTemp[0] = a.x; mTemp[1] = b.x; mTemp[2] = c.x; mTemp[3] = d.x; float minX = Mathf.Min(mTemp); float maxX = Mathf.Max(mTemp); mTemp[0] = a.y; mTemp[1] = b.y; mTemp[2] = c.y; mTemp[3] = d.y; float minY = Mathf.Min(mTemp); float maxY = Mathf.Max(mTemp); if (maxX < mMin.x) return false; if (maxY < mMin.y) return false; if (minX > mMax.x) return false; if (minY > mMax.y) return false; return true; } /// <summary> /// Returns whether the specified world position is within the panel's bounds determined by the clipping rect. /// </summary> public bool IsVisible (Vector3 worldPos) { if (mAlpha < 0.001f) return false; if (mClipping == UIDrawCall.Clipping.None || mClipping == UIDrawCall.Clipping.ConstrainButDontClip) return true; UpdateTransformMatrix(); Vector3 pos = worldToLocal.MultiplyPoint3x4(worldPos); if (pos.x < mMin.x) return false; if (pos.y < mMin.y) return false; if (pos.x > mMax.x) return false; if (pos.y > mMax.y) return false; return true; } /// <summary> /// Returns whether the specified widget is visible by the panel. /// </summary> public bool IsVisible (UIWidget w) { UIPanel p = this; Vector3[] corners = null; while (p != null) { if ((p.mClipping == UIDrawCall.Clipping.None || p.mClipping == UIDrawCall.Clipping.ConstrainButDontClip) && !w.hideIfOffScreen) { p = p.mParentPanel; continue; } if (corners == null) corners = w.worldCorners; if (!p.IsVisible(corners[0], corners[1], corners[2], corners[3])) return false; p = p.mParentPanel; } return true; } /// <summary> /// Whether the specified widget is going to be affected by this panel in any way. /// </summary> public bool Affects (UIWidget w) { if (w == null) return false; UIPanel expected = w.panel; if (expected == null) return false; UIPanel p = this; while (p != null) { if (p == expected) return true; if (!p.hasCumulativeClipping) return false; p = p.mParentPanel; } return false; } /// <summary> /// Causes all draw calls to be re-created on the next update. /// </summary> [ContextMenu("Force Refresh")] public void RebuildAllDrawCalls () { mRebuild = true; } /// <summary> /// Invalidate the panel's draw calls, forcing them to be rebuilt on the next update. /// This call also affects all children. /// </summary> public void SetDirty () { for (int i = 0, imax = drawCalls.Count; i < imax; ++i) drawCalls[i].isDirty = true; Invalidate(true); } /// <summary> /// Cache components. /// </summary> void Awake () { mGo = gameObject; mTrans = transform; mHalfPixelOffset = (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.XBOX360 || Application.platform == RuntimePlatform.WindowsWebPlayer || Application.platform == RuntimePlatform.WindowsEditor); // Only DirectX 9 needs the half-pixel offset if (mHalfPixelOffset && SystemInfo.graphicsDeviceVersion.Contains("Direct3D")) mHalfPixelOffset = (SystemInfo.graphicsShaderLevel < 40); } /// <summary> /// Find the parent panel, if we have one. /// </summary> void FindParent () { Transform parent = cachedTransform.parent; mParentPanel = (parent != null) ? NGUITools.FindInParents<UIPanel>(parent.gameObject) : null; } /// <summary> /// Find the parent panel, if we have one. /// </summary> public override void ParentHasChanged () { base.ParentHasChanged(); FindParent(); } /// <summary> /// Layer is used to ensure that if it changes, widgets get moved as well. /// </summary> protected override void OnStart () { mLayer = mGo.layer; } /// <summary> /// Reset the frame IDs. /// </summary> protected override void OnEnable () { mRebuild = true; mAlphaFrameID = -1; mMatrixFrame = -1; OnStart(); base.OnEnable(); mMatrixFrame = -1; } /// <summary> /// Mark all widgets as having been changed so the draw calls get re-created. /// </summary> protected override void OnInit () { if (list.Contains(this)) return; base.OnInit(); FindParent(); // Apparently having a rigidbody helps #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 if (rigidbody == null && mParentPanel == null) #else if (GetComponent<Rigidbody>() == null && mParentPanel == null) #endif { UICamera uic = (anchorCamera != null) ? mCam.GetComponent<UICamera>() : null; if (uic != null) { if (uic.eventType == UICamera.EventType.UI_3D || uic.eventType == UICamera.EventType.World_3D) { Rigidbody rb = gameObject.AddComponent<Rigidbody>(); rb.isKinematic = true; rb.useGravity = false; } // It's unclear if this helps 2D physics or not, so leaving it disabled for now. // Note that when enabling this, the 'if (rigidbody == null)' statement above should be adjusted as well. //else //{ // Rigidbody2D rb = gameObject.AddComponent<Rigidbody2D>(); // rb.isKinematic = true; //} } } mRebuild = true; mAlphaFrameID = -1; mMatrixFrame = -1; list.Add(this); list.Sort(CompareFunc); } /// <summary> /// Destroy all draw calls we've created when this script gets disabled. /// </summary> protected override void OnDisable () { for (int i = 0, imax = drawCalls.Count; i < imax; ++i) { UIDrawCall dc = drawCalls[i]; UIDrawCall.Destroy(dc); } drawCalls.Clear(); list.Remove(this); mAlphaFrameID = -1; mMatrixFrame = -1; if (list.Count == 0) { UIDrawCall.ReleaseAll(); mUpdateFrame = -1; } base.OnDisable(); } /// <summary> /// Update the world-to-local transform matrix as well as clipping bounds. /// </summary> void UpdateTransformMatrix () { int fc = Time.frameCount; if (mMatrixFrame != fc) { mMatrixFrame = fc; worldToLocal = cachedTransform.worldToLocalMatrix; Vector2 size = GetViewSize() * 0.5f; float x = mClipOffset.x + mClipRange.x; float y = mClipOffset.y + mClipRange.y; mMin.x = x - size.x; mMin.y = y - size.y; mMax.x = x + size.x; mMax.y = y + size.y; } } /// <summary> /// Update the edges after the anchors have been updated. /// </summary> protected override void OnAnchor () { // No clipping = no edges to anchor if (mClipping == UIDrawCall.Clipping.None) return; Transform trans = cachedTransform; Transform parent = trans.parent; Vector2 size = GetViewSize(); Vector2 offset = trans.localPosition; float lt, bt, rt, tt; // Attempt to fast-path if all anchors match if (leftAnchor.target == bottomAnchor.target && leftAnchor.target == rightAnchor.target && leftAnchor.target == topAnchor.target) { Vector3[] sides = leftAnchor.GetSides(parent); if (sides != null) { lt = NGUIMath.Lerp(sides[0].x, sides[2].x, leftAnchor.relative) + leftAnchor.absolute; rt = NGUIMath.Lerp(sides[0].x, sides[2].x, rightAnchor.relative) + rightAnchor.absolute; bt = NGUIMath.Lerp(sides[3].y, sides[1].y, bottomAnchor.relative) + bottomAnchor.absolute; tt = NGUIMath.Lerp(sides[3].y, sides[1].y, topAnchor.relative) + topAnchor.absolute; } else { // Anchored to a single transform Vector2 lp = GetLocalPos(leftAnchor, parent); lt = lp.x + leftAnchor.absolute; bt = lp.y + bottomAnchor.absolute; rt = lp.x + rightAnchor.absolute; tt = lp.y + topAnchor.absolute; } } else { // Left anchor point if (leftAnchor.target) { Vector3[] sides = leftAnchor.GetSides(parent); if (sides != null) { lt = NGUIMath.Lerp(sides[0].x, sides[2].x, leftAnchor.relative) + leftAnchor.absolute; } else { lt = GetLocalPos(leftAnchor, parent).x + leftAnchor.absolute; } } else lt = mClipRange.x - 0.5f * size.x; // Right anchor point if (rightAnchor.target) { Vector3[] sides = rightAnchor.GetSides(parent); if (sides != null) { rt = NGUIMath.Lerp(sides[0].x, sides[2].x, rightAnchor.relative) + rightAnchor.absolute; } else { rt = GetLocalPos(rightAnchor, parent).x + rightAnchor.absolute; } } else rt = mClipRange.x + 0.5f * size.x; // Bottom anchor point if (bottomAnchor.target) { Vector3[] sides = bottomAnchor.GetSides(parent); if (sides != null) { bt = NGUIMath.Lerp(sides[3].y, sides[1].y, bottomAnchor.relative) + bottomAnchor.absolute; } else { bt = GetLocalPos(bottomAnchor, parent).y + bottomAnchor.absolute; } } else bt = mClipRange.y - 0.5f * size.y; // Top anchor point if (topAnchor.target) { Vector3[] sides = topAnchor.GetSides(parent); if (sides != null) { tt = NGUIMath.Lerp(sides[3].y, sides[1].y, topAnchor.relative) + topAnchor.absolute; } else { tt = GetLocalPos(topAnchor, parent).y + topAnchor.absolute; } } else tt = mClipRange.y + 0.5f * size.y; } // Take the offset into consideration lt -= offset.x + mClipOffset.x; rt -= offset.x + mClipOffset.x; bt -= offset.y + mClipOffset.y; tt -= offset.y + mClipOffset.y; // Calculate the new position, width and height float newX = Mathf.Lerp(lt, rt, 0.5f); float newY = Mathf.Lerp(bt, tt, 0.5f); float w = rt - lt; float h = tt - bt; float minx = Mathf.Max(2f, mClipSoftness.x); float miny = Mathf.Max(2f, mClipSoftness.y); if (w < minx) w = minx; if (h < miny) h = miny; // Update the clipping range baseClipRegion = new Vector4(newX, newY, w, h); } static int mUpdateFrame = -1; /// <summary> /// Update all panels and draw calls. /// </summary> void LateUpdate () { #if UNITY_EDITOR if (mUpdateFrame != Time.frameCount || !Application.isPlaying) #else if (mUpdateFrame != Time.frameCount) #endif { mUpdateFrame = Time.frameCount; // Update each panel in order for (int i = 0, imax = list.Count; i < imax; ++i) list[i].UpdateSelf(); int rq = 3000; // Update all draw calls, making them draw in the right order for (int i = 0, imax = list.Count; i < imax; ++i) { UIPanel p = list[i]; if (p.renderQueue == RenderQueue.Automatic) { p.startingRenderQueue = rq; p.UpdateDrawCalls(); rq += p.drawCalls.Count; } else if (p.renderQueue == RenderQueue.StartAt) { p.UpdateDrawCalls(); if (p.drawCalls.Count != 0) rq = Mathf.Max(rq, p.startingRenderQueue + p.drawCalls.Count); } else // Explicit { p.UpdateDrawCalls(); if (p.drawCalls.Count != 0) rq = Mathf.Max(rq, p.startingRenderQueue + 1); } } } } /// <summary> /// Update the panel, all of its widgets and draw calls. /// </summary> void UpdateSelf () { mUpdateTime = RealTime.time; UpdateTransformMatrix(); UpdateLayers(); UpdateWidgets(); if (mRebuild) { mRebuild = false; FillAllDrawCalls(); } else { for (int i = 0; i < drawCalls.Count; ) { UIDrawCall dc = drawCalls[i]; if (dc.isDirty && !FillDrawCall(dc)) { UIDrawCall.Destroy(dc); drawCalls.RemoveAt(i); continue; } ++i; } } if (mUpdateScroll) { mUpdateScroll = false; UIScrollView sv = GetComponent<UIScrollView>(); if (sv != null) sv.UpdateScrollbars(); } } /// <summary> /// Immediately sort all child widgets. /// </summary> public void SortWidgets () { mSortWidgets = false; widgets.Sort(UIWidget.PanelCompareFunc); } /// <summary> /// Fill the geometry fully, processing all widgets and re-creating all draw calls. /// </summary> void FillAllDrawCalls () { for (int i = 0; i < drawCalls.Count; ++i) { if (drawCalls[i] != null) UIDrawCall.Destroy(drawCalls[i]); } drawCalls.Clear(); Material mat = null; Texture tex = null; Shader sdr = null; UIDrawCall dc = null; int count = 0; if (mSortWidgets) SortWidgets(); for (int i = 0; i < widgets.Count; ++i) { UIWidget w = widgets[i]; if (w.isVisible && w.hasVertices) { //Debug.LogError("999999999"); Material mt = w.material; Texture tx = w.mainTexture; Shader sd = w.shader; if (mat != mt || tex != tx || sdr != sd && !w.IsMyWidget)// { if (dc != null && dc.verts.size != 0) { drawCalls.Add(dc); dc.UpdateGeometry(count); dc.onRender = mOnRender; mOnRender = null; count = 0; dc = null; } mat = mt; tex = tx; sdr = sd; } if (mat != null || sdr != null || tex != null || w.IsMyWidget)//wycm || w.IsMyWidget { if (dc == null || w.IsMyWidget) { if (w.IsMyWidget) { dc = new UIDrawCall(); //UIDrawCall.Create(this, null, null, null, w.gameObject.name, true); drawCalls.Add(dc); } else { dc = UIDrawCall.Create(this, mat, tex, sdr); } dc.depthStart = w.depth; dc.depthEnd = dc.depthStart; dc.panel = this; } else { int rd = w.depth; if (rd < dc.depthStart) dc.depthStart = rd; if (rd > dc.depthEnd) dc.depthEnd = rd; } w.drawCall = dc; ++count; if (w.IsMyWidget) { //dc = UIDrawCall.Create(this, null, null, null, w.gameObject.name, true); //dc = new UIDrawCall(); dc.IsMyWidget = true; //w.drawCall.renderQueue = startingRenderQueue + i; dc.MyWidget = w; //dc.panel = this; //drawCalls.Add(dc); Debug.LogError("IsMyWidget"); //w.drawCall = dc; //w.resetdeth(startingRenderQueue + i); } else { if (generateNormals) w.WriteToBuffers(dc.verts, dc.uvs, dc.cols, dc.norms, dc.tans); else w.WriteToBuffers(dc.verts, dc.uvs, dc.cols, null, null); if (w.mOnRender != null) { if (mOnRender == null) mOnRender = w.mOnRender; else mOnRender += w.mOnRender; } } } } else w.drawCall = null; } if (dc != null && dc.verts.size != 0) { drawCalls.Add(dc); dc.UpdateGeometry(count); dc.onRender = mOnRender; mOnRender = null; } } UIDrawCall.OnRenderCallback mOnRender; /// <summary> /// Fill the geometry for the specified draw call. /// </summary> bool FillDrawCall (UIDrawCall dc) { if (dc != null) { dc.isDirty = false; int count = 0; for (int i = 0; i < widgets.Count; ) { UIWidget w = widgets[i]; if (w == null) { #if UNITY_EDITOR Debug.LogError("This should never happen"); #endif widgets.RemoveAt(i); continue; } if (w.drawCall == dc) { if (w.isVisible && w.hasVertices) { ++count; if (generateNormals) w.WriteToBuffers(dc.verts, dc.uvs, dc.cols, dc.norms, dc.tans); else w.WriteToBuffers(dc.verts, dc.uvs, dc.cols, null, null); if (w.mOnRender != null) { if (mOnRender == null) mOnRender = w.mOnRender; else mOnRender += w.mOnRender; } } else w.drawCall = null; } ++i; } if (dc.verts.size != 0) { dc.UpdateGeometry(count); dc.onRender = mOnRender; mOnRender = null; return true; } } return false; } /// <summary> /// Update all draw calls associated with the panel. /// </summary> void UpdateDrawCalls () { Transform trans = cachedTransform; bool isUI = usedForUI; if (clipping != UIDrawCall.Clipping.None) { drawCallClipRange = finalClipRegion; drawCallClipRange.z *= 0.5f; drawCallClipRange.w *= 0.5f; } else drawCallClipRange = Vector4.zero; int w = Screen.width; int h = Screen.height; // Legacy functionality if (drawCallClipRange.z == 0f) drawCallClipRange.z = w * 0.5f; if (drawCallClipRange.w == 0f) drawCallClipRange.w = h * 0.5f; // DirectX 9 half-pixel offset if (halfPixelOffset) { drawCallClipRange.x -= 0.5f; drawCallClipRange.y += 0.5f; } Vector3 pos; if (isUI) { Transform parent = cachedTransform.parent; pos = cachedTransform.localPosition; if (clipping != UIDrawCall.Clipping.None) { pos.x = Mathf.RoundToInt(pos.x); pos.y = Mathf.RoundToInt(pos.y); } if (parent != null) pos = parent.TransformPoint(pos); pos += drawCallOffset; } else pos = trans.position; Quaternion rot = trans.rotation; Vector3 scale = trans.lossyScale; for (int i = 0; i < drawCalls.Count; ++i) { UIDrawCall dc = drawCalls[i]; if (dc.IsMyWidget) { dc.renderQueue = startingRenderQueue + i; if (dc.MyWidget != null) dc.MyWidget.resetdeth(startingRenderQueue + i); } else { Transform t = dc.cachedTransform; t.position = pos; t.rotation = rot; t.localScale = scale; dc.renderQueue = (renderQueue == RenderQueue.Explicit) ? startingRenderQueue : startingRenderQueue + i; dc.alwaysOnScreen = alwaysOnScreen && (mClipping == UIDrawCall.Clipping.None || mClipping == UIDrawCall.Clipping.ConstrainButDontClip); dc.sortingOrder = mSortingOrder; dc.clipTexture = mClipTexture; } } } /// <summary> /// Update the widget layers if the panel's layer has changed. /// </summary> void UpdateLayers () { // Always move widgets to the panel's layer if (mLayer != cachedGameObject.layer) { mLayer = mGo.layer; for (int i = 0, imax = widgets.Count; i < imax; ++i) { UIWidget w = widgets[i]; if (w && w.parent == this) w.gameObject.layer = mLayer; } ResetAnchors(); for (int i = 0; i < drawCalls.Count; ++i) drawCalls[i].gameObject.layer = mLayer; } } bool mForced = false; /// <summary> /// Update all of the widgets belonging to this panel. /// </summary> void UpdateWidgets() { #if UNITY_EDITOR bool forceVisible = cullWhileDragging ? false : (Application.isPlaying && mCullTime > mUpdateTime); #else bool forceVisible = cullWhileDragging ? false : (mCullTime > mUpdateTime); #endif bool changed = false; if (mForced != forceVisible) { mForced = forceVisible; mResized = true; } bool clipped = hasCumulativeClipping; // Update all widgets for (int i = 0, imax = widgets.Count; i < imax; ++i) { UIWidget w = widgets[i]; // If the widget is visible, update it if (w.panel == this && w.enabled) { #if UNITY_EDITOR // When an object is dragged from Project view to Scene view, its Z is... // odd, to say the least. Force it if possible. if (!Application.isPlaying) { Transform t = w.cachedTransform; if (t.hideFlags != HideFlags.HideInHierarchy) { t = (t.parent != null && t.parent.hideFlags == HideFlags.HideInHierarchy) ? t.parent : null; } if (t != null) { for (; ; ) { if (t.parent == null) break; if (t.parent.hideFlags == HideFlags.HideInHierarchy) t = t.parent; else break; } if (t != null) { Vector3 pos = t.localPosition; pos.x = Mathf.Round(pos.x); pos.y = Mathf.Round(pos.y); pos.z = 0f; if (Vector3.SqrMagnitude(t.localPosition - pos) > 0.0001f) t.localPosition = pos; } } } #endif int frame = Time.frameCount; // First update the widget's transform if (w.UpdateTransform(frame) || mResized) { // Only proceed to checking the widget's visibility if it actually moved bool vis = forceVisible || (w.CalculateCumulativeAlpha(frame) > 0.001f); w.UpdateVisibility(vis, forceVisible || ((clipped || w.hideIfOffScreen) ? IsVisible(w) : true)); } // Update the widget's geometry if necessary if (w.UpdateGeometry(frame)) { changed = true; if (!mRebuild) { if (w.drawCall != null) { w.drawCall.isDirty = true; } else { // Find an existing draw call, if possible FindDrawCall(w); } } } } } // Inform the changed event listeners if (changed && onGeometryUpdated != null) onGeometryUpdated(); mResized = false; } /// <summary> /// Insert the specified widget into one of the existing draw calls if possible. /// If it's not possible, and a new draw call is required, 'null' is returned /// because draw call creation is a delayed operation. /// </summary> public UIDrawCall FindDrawCall (UIWidget w) { Material mat = w.material; Texture tex = w.mainTexture; int depth = w.depth; for (int i = 0; i < drawCalls.Count; ++i) { UIDrawCall dc = drawCalls[i]; int dcStart = (i == 0) ? int.MinValue : drawCalls[i - 1].depthEnd + 1; int dcEnd = (i + 1 == drawCalls.Count) ? int.MaxValue : drawCalls[i + 1].depthStart - 1; if (dcStart <= depth && dcEnd >= depth) { if (dc.baseMaterial == mat && dc.mainTexture == tex) { if (w.isVisible) { w.drawCall = dc; if (w.hasVertices) dc.isDirty = true; return dc; } } else mRebuild = true; return null; } } mRebuild = true; return null; } /// <summary> /// Make the following widget be managed by the panel. /// </summary> public void AddWidget (UIWidget w) { mUpdateScroll = true; if (widgets.Count == 0) { widgets.Add(w); } else if (mSortWidgets) { widgets.Add(w); SortWidgets(); } else if (UIWidget.PanelCompareFunc(w, widgets[0]) == -1) { widgets.Insert(0, w); } else { for (int i = widgets.Count; i > 0; ) { if (UIWidget.PanelCompareFunc(w, widgets[--i]) == -1) continue; widgets.Insert(i+1, w); break; } } FindDrawCall(w); } /// <summary> /// Remove the widget from its current draw call, invalidating everything as needed. /// </summary> public void RemoveWidget (UIWidget w) { if (widgets.Remove(w) && w.drawCall != null) { int depth = w.depth; if (depth == w.drawCall.depthStart || depth == w.drawCall.depthEnd) mRebuild = true; w.drawCall.isDirty = true; w.drawCall = null; } } /// <summary> /// Immediately refresh the panel. /// </summary> public void Refresh () { mRebuild = true; mUpdateFrame = -1; if (list.Count > 0) list[0].LateUpdate(); } // <summary> /// Calculate the offset needed to be constrained within the panel's bounds. /// </summary> public virtual Vector3 CalculateConstrainOffset (Vector2 min, Vector2 max) { Vector4 cr = finalClipRegion; float offsetX = cr.z * 0.5f; float offsetY = cr.w * 0.5f; Vector2 minRect = new Vector2(min.x, min.y); Vector2 maxRect = new Vector2(max.x, max.y); Vector2 minArea = new Vector2(cr.x - offsetX, cr.y - offsetY); Vector2 maxArea = new Vector2(cr.x + offsetX, cr.y + offsetY); if (softBorderPadding && clipping == UIDrawCall.Clipping.SoftClip) { minArea.x += mClipSoftness.x; minArea.y += mClipSoftness.y; maxArea.x -= mClipSoftness.x; maxArea.y -= mClipSoftness.y; } return NGUIMath.ConstrainRect(minRect, maxRect, minArea, maxArea); } /// <summary> /// Constrain the current target position to be within panel bounds. /// </summary> public bool ConstrainTargetToBounds (Transform target, ref Bounds targetBounds, bool immediate) { Vector3 min = targetBounds.min; Vector3 max = targetBounds.max; float ps = 1f; if (mClipping == UIDrawCall.Clipping.None) { UIRoot rt = root; if (rt != null) ps = rt.pixelSizeAdjustment; } if (ps != 1f) { min /= ps; max /= ps; } Vector3 offset = CalculateConstrainOffset(min, max) * ps; if (offset.sqrMagnitude > 0f) { if (immediate) { target.localPosition += offset; targetBounds.center += offset; SpringPosition sp = target.GetComponent<SpringPosition>(); if (sp != null) sp.enabled = false; } else { SpringPosition sp = SpringPosition.Begin(target.gameObject, target.localPosition + offset, 13f); sp.ignoreTimeScale = true; sp.worldSpace = false; } return true; } return false; } /// <summary> /// Constrain the specified target to be within the panel's bounds. /// </summary> public bool ConstrainTargetToBounds (Transform target, bool immediate) { Bounds bounds = NGUIMath.CalculateRelativeWidgetBounds(cachedTransform, target); return ConstrainTargetToBounds(target, ref bounds, immediate); } /// <summary> /// Find the UIPanel responsible for handling the specified transform. /// </summary> static public UIPanel Find (Transform trans) { return Find(trans, false, -1); } /// <summary> /// Find the UIPanel responsible for handling the specified transform. /// </summary> static public UIPanel Find (Transform trans, bool createIfMissing) { return Find(trans, createIfMissing, -1); } /// <summary> /// Find the UIPanel responsible for handling the specified transform. /// </summary> static public UIPanel Find (Transform trans, bool createIfMissing, int layer) { UIPanel panel = NGUITools.FindInParents<UIPanel>(trans); if (panel != null) return panel; while (trans.parent != null) trans = trans.parent; return createIfMissing ? NGUITools.CreateUI(trans, false, layer) : null; } /// <summary> /// Get the size of the game window in pixels. /// </summary> public Vector2 GetWindowSize () { UIRoot rt = root; Vector2 size = NGUITools.screenSize; if (rt != null) size *= rt.GetPixelSizeAdjustment(Mathf.RoundToInt(size.y)); return size; } /// <summary> /// Panel's size -- which is either the clipping rect, or the screen dimensions. /// </summary> public Vector2 GetViewSize () { if (mClipping != UIDrawCall.Clipping.None) return new Vector2(mClipRange.z, mClipRange.w); Vector2 size = NGUITools.screenSize; //UIRoot rt = root; //if (rt != null) size *= rt.pixelSizeAdjustment; return size; } #if UNITY_EDITOR /// <summary> /// Draw a visible pink outline for the clipped area. /// </summary> void OnDrawGizmos () { if (anchorCamera == null) return; bool clip = (mClipping != UIDrawCall.Clipping.None); Transform t = clip ? transform : mCam.transform; Vector3[] corners = worldCorners; for (int i = 0; i < 4; ++i) corners[i] = t.InverseTransformPoint(corners[i]); Vector3 pos = Vector3.Lerp(corners[0], corners[2], 0.5f); Vector3 size = corners[2] - corners[0]; GameObject go = UnityEditor.Selection.activeGameObject; bool isUsingThisPanel = (go != null) && (NGUITools.FindInParents<UIPanel>(go) == this); bool isSelected = (UnityEditor.Selection.activeGameObject == gameObject); bool detailedView = (isSelected && isUsingThisPanel); bool detailedClipped = detailedView && mClipping == UIDrawCall.Clipping.SoftClip; Gizmos.matrix = t.localToWorldMatrix; #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6 if (isUsingThisPanel && !clip && mCam.isOrthoGraphic) #else if (isUsingThisPanel && !clip && mCam.orthographic) #endif { UIRoot rt = root; if (rt != null && rt.scalingStyle != UIRoot.Scaling.Flexible) { float width = rt.manualWidth; float height = rt.manualHeight; float x0 = -0.5f * width; float y0 = -0.5f * height; float x1 = x0 + width; float y1 = y0 + height; corners[0] = new Vector3(x0, y0); corners[1] = new Vector3(x0, y1); corners[2] = new Vector3(x1, y1); corners[3] = new Vector3(x1, y0); Vector3 szPos = Vector3.Lerp(corners[0], corners[2], 0.5f); Vector3 szSize = corners[2] - corners[0]; Gizmos.color = new Color(0f, 0.75f, 1f); Gizmos.DrawWireCube(szPos, szSize); } } Gizmos.color = (isUsingThisPanel && !detailedClipped) ? new Color(1f, 0f, 0.5f) : new Color(0.5f, 0f, 0.5f); Gizmos.DrawWireCube(pos, size); if (detailedView) { if (detailedClipped) { Gizmos.color = new Color(1f, 0f, 0.5f); size.x -= mClipSoftness.x * 2f; size.y -= mClipSoftness.y * 2f; Gizmos.DrawWireCube(pos, size); } } } #endif // UNITY_EDITOR } Assets/NGUI/Scripts/UI/UIPanel.cs(907,44): error CS0619: `UnityEngine.RuntimePlatform.WindowsWebPlayer' is obsolete: `WebPlayer export is no longer supported in Unity 5.4+.' 这个代码是Unity5.3.3f1版本的,现在升级到Unity 2017.4.0f1 (64-bit)版本
最新发布
07-08
《垃圾回收手册:自动内存管理的艺术》是一本关于计算机科学中内存管理的重要参考书籍。它详细介绍了垃圾回收的概念、原理和技术,以及如何通过自动内存管理来优化程序的性能和效率。 垃圾回收是一种自动化的内存管理技术,可以帮助程序员解决内存泄漏和内存碎片等问题。它通过检测程序中不再使用的对象,并自动回收它们所占用的内存空间,从而提高程序的内存利用率和运行效率。 该手册分为六个部分,分别是垃圾回收基础、垃圾回收算法、垃圾回收实现、垃圾回收与性能、垃圾回收与扩展以及案例研究。每个部分都涵盖了大量的理论知识和实践经验。 这本书首先介绍了垃圾回收的基本概念和术语,包括垃圾对象、引用、根集等。然后详细介绍了几种常见的垃圾回收算法,如标记-清除算法、复制算法和标记-整理算法等。它还讨论了如何实现一个高效的垃圾回收器,包括内存分配和回收的策略、并发垃圾回收和增量垃圾回收等技术。 此外,该手册还探讨了垃圾回收与程序性能的关系。它介绍了如何通过调优垃圾回收器的参数和策略来改善程序的性能,并提供了一些实用的性能分析工具和方法。 最后,该手册还包括了一些案例研究,通过分析真实的垃圾回收系统和应用程序,展示了垃圾回收技术在实际中的应用和优化方法。 总的来说,《垃圾回收手册:自动内存管理的艺术》是一本全面而深入的关于垃圾回收的参考书籍。它不仅可以帮助读者理解垃圾回收的原理和技术,还可以指导读者如何应用这些技术来优化程序的内存管理和性能。无论是专业的软件工程师还是计算机科学的学生,都可以从中受益。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值