স্ট্রাক্টে "নতুন" ব্যবহার করা কি এটিকে গাদা বা স্ট্যাকের জন্য বরাদ্দ করে?


290

আপনি যখন newঅপারেটর দিয়ে কোনও শ্রেণীর উদাহরণ তৈরি করেন , তখন গাদাটিতে মেমরি বরাদ্দ হয়ে যায়। আপনি যখন newঅপারেটরের সাথে কোনও কাঠামোর উদাহরণ তৈরি করেন সেখানে মেমরিটি বরাদ্দ হয় কোথায়, গাদা বা স্ট্যাকের উপর?

উত্তর:


305

ঠিক আছে, আসুন দেখুন আমি এটি আরও পরিষ্কার করে তুলতে পারি কিনা।

প্রথমত, অ্যাশ সঠিক: প্রশ্নটি কোথায় মানের ধরণের ভেরিয়েবল বরাদ্দ করা হয় তা নিয়ে নয় । এটি একটি আলাদা প্রশ্ন - এবং যার উত্তর কেবল "স্ট্যাকের উপরে" নয়। এটি এর চেয়ে জটিল (এবং সি # 2 আরও জটিল করে তুলেছে)। আমার এই বিষয়ে একটি নিবন্ধ আছে এবং অনুরোধ করা হলে এটিতে প্রসারিত হবে তবে কেবল অপারেটরের সাথে কাজ করব।new

দ্বিতীয়ত, এগুলি সমস্তই নির্ভর করে আপনি কোন স্তরের কথা বলছেন on আমি সংস্থাপকটি উত্স কোডটি কী করে, আইএল এটি তৈরির শর্তে কী করে তা দেখছি। এটি অনেক বেশি সম্ভব যে JIT সংকলক যথেষ্ট পরিমাণে "যৌক্তিক" বরাদ্দকে অপ্টিমাইজ করার ক্ষেত্রে চতুর কাজ করবে।

তৃতীয়ত, আমি জেনেরিকগুলি উপেক্ষা করছি, বেশিরভাগ কারণেই আমি আসলে উত্তরটি জানি না এবং আংশিক কারণ এটি জিনিসগুলিকে খুব জটিল করে তুলবে।

অবশেষে, এই সমস্তগুলি কেবলমাত্র বর্তমান বাস্তবায়ন সহ। সি # স্পেস এর বেশিরভাগ নির্দিষ্ট করে না - এটি কার্যকরভাবে কার্যকর করার একটি বিবরণ। এমন যারা আছেন যারা বিশ্বাস করেন যে পরিচালিত কোড বিকাশকারীদের সত্যই যত্ন নেওয়া উচিত নয়। আমি নিশ্চিত নই যে আমি এতদূর যাব, তবে এমন এক পৃথিবীর কল্পনা করা মূল্যবান যেখানে বাস্তবে সমস্ত স্থানীয় ভেরিয়েবলগুলি স্তূপে বাস করে - যা এখনও সেই অনুমানের সাথে সামঞ্জস্যপূর্ণ would


newঅপারেটরের সাথে মান ধরণের দুটি পৃথক পরিস্থিতি রয়েছে : আপনি হয় প্যারামিটারলেস কনস্ট্রাক্টর (যেমন new Guid()) বা একটি প্যারামিটারফুল কনস্ট্রাক্টর (যেমন new Guid(someString)) কল করতে পারেন । এগুলি উল্লেখযোগ্যভাবে আলাদা আইএল উত্পন্ন করে। কেন তা বোঝার জন্য, আপনাকে সি # এবং সি এল এল স্পেকের তুলনা করতে হবে: সি # অনুসারে সমস্ত মান ধরণের একটি প্যারামিটারলেস কনস্ট্রাক্টর রয়েছে। সিএলআই স্পেক অনুসারে কোনও মান ধরণের প্যারামিটারলেস কনস্ট্রাক্টর নেই। (কিছু সময়ের প্রতিচ্ছবি সহ একটি মান ধরণের নির্মাতাদের আনুন - আপনি কোনও প্যারামিটারলেস পাবেন না))

কারণ এটি ভাষা সামঞ্জস্যপূর্ণ রাখে এটি একটি কন্সট্রাকটর হিসাবে "শূণ্যসমূহ সঙ্গে একটি মান আরম্ভ" চিকিত্সা C # এর জন্য জ্ঞান করে তোলে - আপনি মনে করতে পারেন new(...)হিসাবে সবসময় একটি কন্সট্রাকটর আহ্বান। সিএলআই-এর পক্ষে এটি আলাদাভাবে চিন্তা করা বোধগম্য হয়, কারণ কল করার কোনও আসল কোড নেই - এবং অবশ্যই কোনও টাইপ-নির্দিষ্ট কোড নেই।

আপনি মানটি আরম্ভ করার পরে আপনি কী করতে যাচ্ছেন তাও এটি একটি পার্থক্য করে। আইএল এর জন্য ব্যবহৃত

Guid localVariable = new Guid(someString);

ব্যবহৃত আইএল থেকে আলাদা:

myInstanceOrStaticVariable = new Guid(someString);

তদ্ব্যতীত, মানটি যদি একটি মধ্যবর্তী মান হিসাবে ব্যবহৃত হয়, উদাহরণস্বরূপ কোনও মেথড কলের জন্য একটি যুক্তি, জিনিসগুলি আবার কিছুটা আলাদা slightly এই সমস্ত পার্থক্য দেখানোর জন্য, এখানে একটি সংক্ষিপ্ত পরীক্ষা প্রোগ্রাম's এটি স্ট্যাটিক ভেরিয়েবল এবং উদাহরণ ভেরিয়েবলের মধ্যে পার্থক্য দেখায় না: আইএল stfldএবং এর মধ্যে পার্থক্য করতে পারে তবে এগুলি stsfldসবই।

using System;

public class Test
{
    static Guid field;

    static void Main() {}
    static void MethodTakingGuid(Guid guid) {}


    static void ParameterisedCtorAssignToField()
    {
        field = new Guid("");
    }

    static void ParameterisedCtorAssignToLocal()
    {
        Guid local = new Guid("");
        // Force the value to be used
        local.ToString();
    }

    static void ParameterisedCtorCallMethod()
    {
        MethodTakingGuid(new Guid(""));
    }

    static void ParameterlessCtorAssignToField()
    {
        field = new Guid();
    }

    static void ParameterlessCtorAssignToLocal()
    {
        Guid local = new Guid();
        // Force the value to be used
        local.ToString();
    }

    static void ParameterlessCtorCallMethod()
    {
        MethodTakingGuid(new Guid());
    }
}

এখানে অপ্রাসঙ্গিক বিটগুলি বাদ দিয়ে ক্লাসের জন্য আইএল (যেমন নপস):

.class public auto ansi beforefieldinit Test extends [mscorlib]System.Object    
{
    // Removed Test's constructor, Main, and MethodTakingGuid.

    .method private hidebysig static void ParameterisedCtorAssignToField() cil managed
    {
        .maxstack 8
        L_0001: ldstr ""
        L_0006: newobj instance void [mscorlib]System.Guid::.ctor(string)
        L_000b: stsfld valuetype [mscorlib]System.Guid Test::field
        L_0010: ret     
    }

    .method private hidebysig static void ParameterisedCtorAssignToLocal() cil managed
    {
        .maxstack 2
        .locals init ([0] valuetype [mscorlib]System.Guid guid)    
        L_0001: ldloca.s guid    
        L_0003: ldstr ""    
        L_0008: call instance void [mscorlib]System.Guid::.ctor(string)    
        // Removed ToString() call
        L_001c: ret
    }

    .method private hidebysig static void ParameterisedCtorCallMethod() cil  managed    
    {   
        .maxstack 8
        L_0001: ldstr ""
        L_0006: newobj instance void [mscorlib]System.Guid::.ctor(string)
        L_000b: call void Test::MethodTakingGuid(valuetype [mscorlib]System.Guid)
        L_0011: ret     
    }

    .method private hidebysig static void ParameterlessCtorAssignToField() cil managed
    {
        .maxstack 8
        L_0001: ldsflda valuetype [mscorlib]System.Guid Test::field
        L_0006: initobj [mscorlib]System.Guid
        L_000c: ret 
    }

    .method private hidebysig static void ParameterlessCtorAssignToLocal() cil managed
    {
        .maxstack 1
        .locals init ([0] valuetype [mscorlib]System.Guid guid)
        L_0001: ldloca.s guid
        L_0003: initobj [mscorlib]System.Guid
        // Removed ToString() call
        L_0017: ret 
    }

    .method private hidebysig static void ParameterlessCtorCallMethod() cil managed
    {
        .maxstack 1
        .locals init ([0] valuetype [mscorlib]System.Guid guid)    
        L_0001: ldloca.s guid
        L_0003: initobj [mscorlib]System.Guid
        L_0009: ldloc.0 
        L_000a: call void Test::MethodTakingGuid(valuetype [mscorlib]System.Guid)
        L_0010: ret 
    }

    .field private static valuetype [mscorlib]System.Guid field
}

আপনি দেখতে পাচ্ছেন, কনস্ট্রাক্টরকে কল করার জন্য প্রচুর বিভিন্ন নির্দেশাবলী ব্যবহৃত হয়েছে:

  • newobj: স্ট্যাকের মান বরাদ্দ করে, একটি প্যারামিটারাইজড কনস্ট্রাক্টরকে কল করে। মধ্যবর্তী মানগুলির জন্য ব্যবহৃত হয়, যেমন কোনও ক্ষেত্রের জন্য বরাদ্দকরণের জন্য বা পদ্ধতি আর্গুমেন্ট হিসাবে ব্যবহার।
  • call instance: ইতিমধ্যে বরাদ্দকৃত স্টোরেজ অবস্থান ব্যবহার করে (স্ট্যাকটিতে থাকুক বা না থাকুক)। স্থানীয় ভেরিয়েবলকে বরাদ্দ করার জন্য এটি উপরের কোডে ব্যবহৃত হয়। যদি একই স্থানীয় ভেরিয়েবলকে বেশ কয়েকটি newকল ব্যবহার করে একাধিকবার একটি মূল্য বরাদ্দ করা হয় তবে এটি কেবল পুরানো মানের শীর্ষে ডেটা শুরু করে - এটি প্রতিবার বেশি স্ট্যাকের স্থান বরাদ্দ করে না
  • initobj: ইতিমধ্যে বরাদ্দকৃত স্টোরেজ অবস্থান ব্যবহার করে এবং কেবল ডেটা মুছবে। এটি আমাদের সমস্ত প্যারামিটারলেস কনস্ট্রাক্টর কলগুলির জন্য ব্যবহৃত হয়, যা স্থানীয় ভেরিয়েবলকে অর্পণ করে। পদ্ধতি কলের জন্য, একটি মধ্যবর্তী স্থানীয় পরিবর্তনশীল কার্যকরভাবে চালু করা হয়েছে, এবং এর মান দ্বারা মুছে ফেলা হয় initobj

আমি আশা করি এটি একই সাথে এটির উপর খানিকটা আলোকপাত করার সময় বিষয়টি কতটা জটিল তা দেখায়। ইন কিছু ধারণাগত অজ্ঞান, এর প্রতি কলের newস্ট্যাক বরাদ্দ স্থান - কিন্তু আমরা দেখা করেছি, যে কি সত্যিই এমনকি আইএল পর্যায়ে ঘটে নয়। আমি একটি বিশেষ ক্ষেত্রে হাইলাইট করতে চাই। এই পদ্ধতিটি গ্রহণ করুন:

void HowManyStackAllocations()
{
    Guid guid = new Guid();
    // [...] Use guid
    guid = new Guid(someBytes);
    // [...] Use guid
    guid = new Guid(someString);
    // [...] Use guid
}

সেই "যৌক্তিকভাবে" 4 টি স্ট্যাক বরাদ্দ রয়েছে - ভেরিয়েবলের জন্য একটি এবং তিনটি newকলের প্রত্যেকটির জন্য একটি - তবে বাস্তবে (সেই নির্দিষ্ট কোডের জন্য) স্ট্যাকটি কেবল একবার বরাদ্দ করা হয়, এবং তারপরে একই স্টোরেজ অবস্থানটি পুনরায় ব্যবহার করা হয়।

সম্পাদনা: শুধু পরিষ্কার হবে, কিছু ক্ষেত্রে এটি একমাত্র সত্য হচ্ছে ... বিশেষ করে, এর মান guidনা দৃশ্যমান যদি হতে হবে Guidকন্সট্রাকটর একটি ব্যতিক্রম, যার কারণে C # এর কম্পাইলার একই স্ট্যাকের স্লট পুনরায় ব্যবহার করতে সক্ষম হয় ছোঁড়ার। আরও বিশদ এবং এর ক্ষেত্রে প্রয়োগ হয় না এমন ক্ষেত্রে মূল্য টাইপ নির্মাণের জন্য এরিক লিপার্টের ব্লগ পোস্টটি দেখুন ।

আমি এই উত্তরটি লেখার ক্ষেত্রে অনেক কিছু শিখেছি - দয়া করে এর কোনও স্পষ্ট না থাকলে স্পষ্টতার জন্য জিজ্ঞাসা করুন!


1
জন, হাউম্যানিস্ট্যাকআলোকেশন উদাহরণ কোডটি ভাল। তবে আপনি এটি গাইডের পরিবর্তে স্ট্রাক্ট ব্যবহার করতে বা একটি নতুন স্ট্রাক্ট উদাহরণ যুক্ত করতে পারেন। আমি মনে করি এটি তখন @ কেদার এর আসল প্রশ্নটি সরাসরি সমাধান করবে।
অ্যাশ

9
গাইড ইতিমধ্যে একটি কাঠামো। এমএসডিএন.মাইক্রোসফট. /en-us/library/system.guid.aspx দেখুন আমি এই প্রশ্নের জন্য একটি রেফারেন্স টাইপ পছন্দ করতাম না :)
জন স্কিটি

1
আপনার সাথে List<Guid>3 টি যুক্ত হয়ে কী হবে? এটি 3 বরাদ্দ (একই আইএল) হবে? তবে তাদের কোথাও
icalন্দ্রজালিক

1
@ অণি: আপনি এরিকের উদাহরণটিতে চেষ্টা / ধরা ব্লক রয়েছে এমন বিষয়টি হারিয়ে ফেলছেন - সুতরাং যদি স্ট্রাক্ট নির্মাণকারীর সময় কোনও ব্যতিক্রম ছুঁড়ে ফেলা হয় তবে আপনাকে নির্মাণকারীর আগে মানটি দেখতে পারা দরকার। আমার উদাহরণে এরকম পরিস্থিতি নেই - যদি কনস্ট্রাক্টর ব্যতিক্রম ব্যর্থ হয় তবে এর মূল্যটি guidকেবল অর্ধ-ওভাররাইট করা হয়েছে কিনা তা বিবেচ্য নয়, যেহেতু এটি দৃশ্যমান হবে না।
জন স্কিটি

2
@ অণি: বাস্তবে এরিক তার পোস্টের নীচের দিকে এটিকে ডেকে বলেছেন: "এখন, ওয়েসনারের বক্তব্য কী হবে? হ্যাঁ, বাস্তবে যদি এটি স্ট্যাক-বরাদ্দকৃত স্থানীয় ভেরিয়েবল (এবং বন্ধের ক্ষেত্র নয়) তবে ঘোষিত হয় কনস্ট্রাক্টর কল হিসাবে বাসা বাঁধার একই স্তরে তখন আমরা একটি নতুন অস্থায়ী করার, অস্থায়ীটি শুরু করার এবং স্থানীয়কে এটির অনুলিপি করার এই অনিয়মকে অতিক্রম করি না that সেই নির্দিষ্ট (এবং সাধারণ) ক্ষেত্রে আমরা অপ্টিমাইজ করতে পারি অস্থায়ী এবং অনুলিপি তৈরি করা কারণ কোনও সি # প্রোগ্রামের পক্ষে পার্থক্যটি পর্যবেক্ষণ করা অসম্ভব! "
জন স্কিটি

40

কোনও স্ট্রাক্টের ক্ষেত্র সমেত মেমরিটি স্ট্যাক বা গর্তের উপর নির্ভর করে পরিস্থিতি অনুসারে বরাদ্দ করা যেতে পারে। যদি স্ট্রাক্ট-টাইপ ভেরিয়েবল স্থানীয় ভেরিয়েবল বা প্যারামিটার হয় যা কিছু বেনামী প্রতিনিধি বা পুনরাবৃত্ত শ্রেণীর দ্বারা ক্যাপচার করা হয় না, তবে এটি স্ট্যাকের জন্য বরাদ্দ করা হবে। যদি ভেরিয়েবলটি কোনও শ্রেণির অংশ হয়, তবে এটি ক্লাসের মধ্যে স্তূপে বরাদ্দ করা হবে।

যদি স্ট্রাকটি গাদাতে বরাদ্দ দেওয়া হয়, তবে নতুন অপারেটরকে কল করা মেমরির বরাদ্দ করা আসলে প্রয়োজন হয় না। একমাত্র উদ্দেশ্য হ'ল নির্মাণকারীর মধ্যে যা আছে তা অনুসারে ক্ষেত্রের মানগুলি নির্ধারণ করা। যদি কনস্ট্রাক্টরকে না ডাকা হয়, তবে সমস্ত ক্ষেত্র তাদের ডিফল্ট মান (0 বা নাল) পাবে।

একইভাবে স্ট্যাকের জন্য বরাদ্দ স্ট্রাক্টগুলি বাদে, সি # এর জন্য সমস্ত স্থানীয় ভেরিয়েবলগুলি ব্যবহারের আগে কিছু মান নির্ধারণ করা প্রয়োজন, সুতরাং আপনাকে কাস্টম কনস্ট্রাক্টর বা ডিফল্ট কনস্ট্রাক্টর কল করতে হবে (কোনও কনস্ট্রাক্টর যা প্যারামিটার নেয় না সর্বদা উপলভ্য থাকে structs মধ্যে)।


13

এটিকে সংক্ষিপ্তভাবে বলতে গেলে নতুন স্ট্রাক্টের জন্য ভুল ব্যবহারকারী, নতুনকে কল করা কেবল কনস্ট্রাক্টরকে কল করে। কাঠামোর একমাত্র সঞ্চয় স্থানটি এটির সংজ্ঞা দেওয়া হয়েছে।

এটি যদি সদস্যের পরিবর্তনশীল হয় তবে এটি সংজ্ঞায়িত যেকোন ক্ষেত্রেই সরাসরি সংরক্ষণ করা হয়, যদি এটি স্থানীয় ভেরিয়েবল বা প্যারামিটার হয় তবে এটি স্ট্যাকের মধ্যে সংরক্ষণ করা হয়।

এটি ক্লাসগুলির সাথে বিপরীতে করুন, যেখানে স্ট্রাক্টটি সম্পূর্ণরূপে সংরক্ষণ করা হত যেখানে রেফারেন্স রয়েছে, অন্যদিকে রেফারেন্সটি কোথাও কোথাও রয়েছে ap (এর মধ্যে সদস্য, স্ট্যাকের স্থানীয় / প্যারামিটার)

এটি C ++ তে কিছুটা দেখার জন্য সহায়তা করতে পারে, যেখানে শ্রেণি / কাঠামোর মধ্যে প্রকৃত পার্থক্য নেই। (ভাষাতে একই রকম নাম রয়েছে তবে তারা কেবলমাত্র জিনিসগুলির ডিফল্ট অ্যাক্সেসিবিলিটি উল্লেখ করে) আপনি যখন নতুন কল করেন তখন আপনি গাদা অবস্থানের একটি পয়েন্টার পান, যখন আপনার কোনও পয়েন্টার ছাড়াই রেফারেন্স থাকে তা সরাসরি স্ট্যাকের মধ্যে সংরক্ষণ করা হয় বা অন্যান্য বস্তুর মধ্যে, আলা সি # তে স্ট্রাক্ট করে।


5

সমস্ত মান ধরণের মতো, স্ট্রাইকগুলি সর্বদা যেখানে ঘোষিত হয়েছিল সেখানে যায় ।

স্ট্রাক্টগুলি কখন ব্যবহার করবেন সে সম্পর্কে আরও তথ্যের জন্য এই প্রশ্নটি এখানে দেখুন । স্ট্রাক্ট সম্পর্কিত আরও কিছু তথ্যের জন্য এবং এই প্রশ্নটি এখানে

সম্পাদনা: আমি দূরত্বে উত্তর দিয়েছিলাম যে তারা সবসময় স্ট্যাকের মধ্যে যায়। এটি ভুল


"স্ট্রাইকগুলি সর্বদা যেখানে যেখানে ঘোষিত হয়েছিল সেখানে যায়", এটি কিছুটা বিভ্রান্তিকর বিভ্রান্তিকর। শ্রেণীর একটি কাঠামো ক্ষেত্র সর্বদা "ধরণের স্মৃতিতে যখন টাইপের কোনও উদাহরণ নির্মিত হয়" তে রাখা হয় - জেফ রিখর। এটি অপ্রত্যক্ষভাবে গাদা হয়ে থাকতে পারে তবে সাধারণ রেফারেন্স টাইপের মতো নয়।
অ্যাশ

না, আমি মনে করি এটি ঠিক ঠিক - যদিও এটি কোনও রেফারেন্স টাইপের মতো নয়। পরিবর্তনশীল জীবনের মান যেখানে এটি ঘোষিত হয়। একটি রেফারেন্স ধরণের ভেরিয়েবলের মান হ'ল প্রকৃত ডেটার পরিবর্তে একটি রেফারেন্স।
জন স্কিটি

সংক্ষেপে, আপনি যখনই কোনও পদ্ধতিতে যে কোনও মান টাইপ তৈরি (ঘোষণা) করেন তবে এটি সর্বদা স্ট্যাকের উপরে তৈরি করা হয়।
অ্যাশ

2
জন, তুমি আমার কথা মিস করছ এই প্রশ্নটি প্রথম জিজ্ঞাসা করার কারণটি হ'ল এটি অনেক বিকাশকারীদের কাছে পরিষ্কার নয় (আমি সিএলআর মাধ্যমে সি # না পড়া পর্যন্ত আমাকে অন্তর্ভুক্ত করা হয়েছে) যেখানে আপনি নতুন অপারেটর তৈরি করতে যদি এটির জন্য স্ট্রাক্ট বরাদ্দ থাকে। "স্ট্রাইক সর্বদা যেখানে ঘোষিত হয়েছিল সেখানে গিয়ে" বলা সুস্পষ্ট উত্তর নয়।
অ্যাশ

1
@ আশ: আমার যদি সময় থাকে তবে আমি যখন কাজ শুরু করব তখন একটি উত্তর লেখার চেষ্টা করব। যদিও ট্রেনে কাভার করার চেষ্টা করা খুব বড় বিষয় তা হল :)
জন স্কিটি

4

আমি সম্ভবত এখানে কিছু মিস করছি তবে কেন আমরা বরাদ্দ সম্পর্কে যত্নশীল?

মান প্রকারগুলি মান দ্বারা পাস হয়;) এবং সুতরাং যেখানে সেগুলি সংজ্ঞায়িত করা হয় তার চেয়ে আলাদা স্কোপে পরিবর্তন করা যায় না। মানটি পরিবর্তন করতে সক্ষম হতে আপনাকে [রেফ] শব্দটি যুক্ত করতে হবে।

রেফারেন্সের ধরণগুলি রেফারেন্স দ্বারা পাস হয় এবং পরিবর্তিত হতে পারে।

অবিচ্ছেদ্য রেফারেন্স ধরণের স্ট্রিং অবশ্যই সর্বাধিক জনপ্রিয়।

অ্যারের বিন্যাস / সূচনা: মানের ধরণ -> শূন্য মেমরি [নাম, জিপ] [নাম, জিপ] রেফারেন্সের ধরণ -> শূন্য মেমরি -> নাল [রেফ] [রেফ]


3
রেফারেন্সের ধরণগুলি রেফারেন্স দ্বারা পাস হয় না - রেফারেন্সগুলি মান দ্বারা পাস হয়। এটা খুব আলাদা।
জন স্কিটি

2

classবা structঘোষণাটি একটি ব্লুপ্রিন্টের মতো যা রান সময়গুলিতে দৃষ্টান্ত বা বস্তু তৈরিতে ব্যবহৃত হয়। আপনি যদি একটি classবা structপরিচিত ব্যক্তিকে সংজ্ঞায়িত করেন তবে ব্যক্তি হ'ল প্রকারের নাম। আপনি যদি ব্যক্তির একটি পরিবর্তনশীল পি প্রকারের ঘোষণা এবং সূচনা করেন তবে পি বলা হয় ব্যক্তির কোনও অবজেক্ট বা উদাহরণ instance একই ব্যক্তি ধরনের একাধিক দৃষ্টান্ত তৈরি করা যেতে পারে, এবং প্রতিটি উদাহরণ হিসেবে বলা যায় তার মান আলাদা থাকতে পারে propertiesএবং fields

classএকটি রেফারেন্স টাইপ। যখন কোনও বস্তু classতৈরি করা হয়, বস্তুটি যে ভেরিয়েবলকে নির্ধারিত হয় কেবল সেই মেমরির একটি রেফারেন্স ধরে। যখন বস্তুর রেফারেন্সটি একটি নতুন ভেরিয়েবলকে বরাদ্দ করা হয়, তখন নতুন ভেরিয়েবলটি মূল বস্তুকে বোঝায়। একটি ভেরিয়েবলের মাধ্যমে করা পরিবর্তনগুলি অন্য ভেরিয়েবলে প্রতিফলিত হয় কারণ তারা উভয়ই একই ডেটা উল্লেখ করে।

structএকটি মান ধরণের। যখন একটি structতৈরি করা হয়, যে ভেরিয়েবলটি structনির্ধারিত হয় তা স্ট্রাক্টের আসল ডেটা ধারণ করে। যখন structনতুন ভেরিয়েবলের জন্য বরাদ্দ করা হয়, এটি অনুলিপি করা হয়। নতুন ভেরিয়েবল এবং মূল ভেরিয়েবলের ফলে একই ডেটার দুটি পৃথক অনুলিপি থাকে। একটি অনুলিপিতে করা পরিবর্তনগুলি অন্য অনুলিপিকে প্রভাবিত করে না।

সাধারণভাবে, classesআরও জটিল আচরণের মডেল হিসাবে ব্যবহার করা হয়, বা এমন কোনও ডেটা যা কোনও classবস্তু তৈরির পরে পরিবর্তিত হতে পারে । Structsছোট ডেটা স্ট্রাকচারের জন্য সেরা উপযুক্ত যা প্রাথমিকভাবে এমন ডেটা ধারণ করে structযা তৈরির পরে পরিবর্তিত হওয়ার উদ্দেশ্যে নয় ।

আরো বেশী...


1

বেশিরভাগ স্ট্রাক্ট যা মান ধরণের হিসাবে বিবেচিত হয়, স্ট্যাকের জন্য বরাদ্দ করা হয়, যখন বস্তুগুলি স্তূপে বরাদ্দ পায়, যখন বস্তুর রেফারেন্স (পয়েন্টার) স্ট্যাকের উপর বরাদ্দ হয়ে যায়।


1

স্ট্রাকগুলিতে স্ট্রোকগুলি বরাদ্দ পায়। এখানে একটি সহায়ক ব্যাখ্যা:

structs

অতিরিক্ত হিসাবে, ক্লাসগুলি যখন NET এর মধ্যে ইনস্ট্যান্ট করা হয় তখন হিপ বা .NET- র সংরক্ষিত মেমরি স্পেসে মেমরি বরাদ্দ করে। স্ট্যাকগুলিতে বরাদ্দের কারণে তড়িঘড়ি করা হলে স্ট্রাক্টগুলি আরও দক্ষতা অর্জন করে। তদ্ব্যতীত, এটি লক্ষ করা উচিত যে স্ট্রাইকগুলির মধ্যে পাসিং পরামিতিগুলি মান দ্বারা সম্পন্ন হয়।


5
যখন স্ট্রাক্ট কোনও শ্রেণীর অংশ হয় তখন এটি কেসটি কভার করে না - কোন মুহুর্তে এটি বস্তুর বাকী ডেটা সহ স্তূপে বাস করে।
জন স্কিটি

1
হ্যাঁ তবে এটি আসলে ফোকাস করে এবং জিজ্ঞাসিত প্রশ্নের উত্তর দেয় answers ভোট দিয়েছেন।
অ্যাশ

... এখনও ভুল এবং বিভ্রান্তিকর অবস্থায়। দুঃখিত, তবে এই প্রশ্নের কোনও সংক্ষিপ্ত উত্তর নেই - জেফরির একমাত্র সম্পূর্ণ উত্তর।
মার্ক গ্র্যাভেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.