ভূমিকা : এই উত্তরটি আগে লেখা হয়েছিল অপ্ট ইন বিল্ট-ইন বৈশিষ্ট্যগুলো -specifically দিক বাস্তবায়িত -were। আমি কেবল পুরানো স্কিমের ক্ষেত্রে প্রয়োগ করা বিভাগগুলি চিহ্নিত করতে ব্লক কোট ব্যবহার করেছি (প্রশ্নটি যখন জিজ্ঞাসা করার সময় প্রয়োগ হয়েছিল)।Copy
পুরানো : মৌলিক প্রশ্নের উত্তর দিতে, আপনি একটি NoCopyমান সংরক্ষণ করে একটি চিহ্নিতকারী ক্ষেত্র যুক্ত করতে পারেন । যেমন
struct Triplet {
one: int,
two: int,
three: int,
_marker: NoCopy
}
আপনি এটি একটি ডেস্ট্রাক্টর ( Dropবৈশিষ্ট্য প্রয়োগের মাধ্যমে ) করেও করতে পারেন , তবে যদি ডেস্ট্রাক্টর কিছু না করে তবে চিহ্নিতকারী প্রকারগুলি ব্যবহার করা পছন্দ হয়।
প্রকারগুলি এখন ডিফল্টরূপে সরানো হয়, এটি হ'ল আপনি যখন কোনও নতুন প্রকারের সংজ্ঞা দেন তখন এটি কার্যকর হয় না Copyযতক্ষণ না আপনি স্পষ্টভাবে আপনার ধরণের জন্য এটি প্রয়োগ করেন:
struct Triplet {
one: i32,
two: i32,
three: i32
}
impl Copy for Triplet {}
বাস্তবায়ন কেবল তখনই বিদ্যমান থাকতে পারে যদি নতুনটিতে থাকা প্রতিটি প্রকার structবা enumনিজেই থাকে Copy। যদি তা না হয় তবে সংকলক একটি ত্রুটি বার্তা প্রিন্ট করবে। টাইপটির যদি বাস্তবায়ন না হয় কেবল তখনই এটি বিদ্যমান থাকতে পারে Drop।
যে প্রশ্নটি আপনি জিজ্ঞাসা করেননি তার জবাব দিতে ... "চাল এবং অনুলিপি নিয়ে কী আছে?":
প্রথমে আমি দুটি পৃথক "অনুলিপি" সংজ্ঞায়িত করব:
- একটি বাইট অনুলিপি , যা কেবল অল্প মাত্রায় কোনও বাইট-বাই-বাইট কোনও বিষয়বস্তু অনুলিপি করছে , নিম্নলিখিত পয়েন্টারগুলি নয়, উদাহরণস্বরূপ যদি আপনার কাছে থাকে তবে
(&usize, u64)এটি একটি 64-বিট কম্পিউটারে 16 বাইট, এবং একটি অগভীর অনুলিপি 16 বাইট নিবে এবং তার প্রতিলিপি করবে মেমরি কিছু অন্যান্য 16-বাইট খণ্ড মান, ছাড়া স্পর্শ usizeএর অন্য প্রান্তে &। এটি, কল করার সমতুল্য memcpy।
- একটি শব্দার্থক অনুলিপি , একটি নতুন (কিছুটা) স্বতন্ত্র উদাহরণ তৈরির জন্য একটি মানটিকে নকল করে যা পুরানোটির সাথে আলাদাভাবে ব্যবহার করা যেতে পারে। উদাহরণস্বরূপ, কোনওটির শব্দার্থক অনুলিপি
Rc<T>কেবলমাত্র রেফারেন্স গণনা বাড়িয়ে তোলে এবং এর একটি শব্দার্থক অনুলিপি Vec<T>একটি নতুন বরাদ্দ তৈরি করা জড়িত, এবং তারপরে সিন্থেটিকভাবে প্রতিটি সঞ্চিত উপাদানকে পুরানো থেকে নতুন করে অনুলিপি করে। এগুলি গভীর অনুলিপি হতে পারে (উদাঃ Vec<T>) বা অগভীর (উদাহরণস্বরূপ Rc<T>সঞ্চিত স্পর্শ করে না T), Cloneকোনওভাবে Tভিতরে থেকে কোনও ধরণের মানকে শব্দার্থভাবে অনুলিপি করতে প্রয়োজনীয় ক্ষুদ্রতম কাজের হিসাবে স্বল্পভাবে সংজ্ঞায়িত &Tহয় T।
মরিচা সি এর মতো, একটি মানের প্রতিটি বাই-মান ব্যবহার একটি বাইট অনুলিপি:
let x: T = ...;
let y: T = x;
fn foo(z: T) -> T {
return z
}
foo(y)
এগুলি বাইট অনুলিপিগুলি হয় না তা Tসরানো হয় বা "অন্তর্নিহিত অনুলিপিযোগ্য"। (স্পষ্টরূপে বলতে গেলে, রান-টাইমে এগুলি অগত্যা আক্ষরিক অর্থে বাই বাইট কপি নয়: সংকলক কোডের আচরণ সংরক্ষণ করা থাকলে অনুলিপিগুলি অনুলিপি করতে মুক্ত to)
যাইহোক, বাইট অনুলিপিগুলির সাথে একটি মৌলিক সমস্যা রয়েছে: আপনি মেমরিতে নকল মানগুলি দিয়ে শেষ করেন, এটির ডেস্ট্রাক্টর থাকলে খুব খারাপ হতে পারে eg
{
let v: Vec<u8> = vec![1, 2, 3];
let w: Vec<u8> = v;
}
যদি wকেবল একটি সাধারণ বাইট অনুলিপি হয় vতবে সেখানে দু'জন ভেক্টর একই বরাদ্দের দিকে ইশারা করত, উভয়ই এটির মুক্তকারী ধ্বংসকারীদের সাথে ... ডাবল ফ্রি তৈরি করে যা একটি সমস্যা। এনবি। এই পুরোপুরি ঠিক হয়ে যাব যদি আমরা একটি শব্দার্থিক কপি করেছিল vমধ্যে w, যেহেতু তারপর wনিজস্ব স্বাধীন হবে Vec<u8>এবং destructors একে অপরের ওপর পদদলিত করা হবে না।
এখানে কয়েকটি সম্ভাব্য সমাধান রয়েছে:
- প্রোগ্রামারটিকে সি এর মতো এটি পরিচালনা করতে দিন (সি তে কোনও ধ্বংসকারী নেই, সুতরাং এটি ততটা খারাপ নয় ... পরিবর্তে আপনি কেবল মেমরি ফাঁস দিয়ে রেখে যান:: পি)
- অন্তর্নিহিতভাবে একটি শব্দার্থক অনুলিপি সম্পাদন করুন, যাতে
wএর নিজস্ব বরাদ্দ রয়েছে, যেমন এর অনুলিপি নির্মাণকারীদের সাথে সি ++।
- মালিকানার স্থানান্তর হিসাবে বাই-মান ব্যবহারগুলি সম্মান করুন, যাতে এটি
vআর ব্যবহার করা যায় না এবং এর ডেস্ট্রাক্টর চালিত না হয়।
শেষটি যা মরিচা করে: একটি পদক্ষেপ কেবলমাত্র একটি মান অনুসারে ব্যবহার যেখানে উত্সটি স্থিতিশীলভাবে অবৈধ হয়, তাই সংকলকটি এখন-অবৈধ মেমরির আরও ব্যবহারকে বাধা দেয়।
let v: Vec<u8> = vec![1, 2, 3];
let w: Vec<u8> = v;
println!("{}", v);
যে ধরণের ডেস্ট্রাক্টর রয়েছে তাদের অবশ্যই বাই-মান (যখন বাইট অনুলিপি করা হয়) ব্যবহার করার সময় চলতে হবে , যেহেতু তাদের কিছু সংস্থান (যেমন একটি মেমরি বরাদ্দ, বা একটি ফাইল হ্যান্ডেল) এর মালিকানা / মালিকানা রয়েছে এবং এটির খুব সম্ভবত সম্ভাবনা নেই যে বাইট অনুলিপিটি এটি সঠিকভাবে নকল করবে মালিকানা
"আচ্ছা ... একটি অন্তর্নিহিত অনুলিপি কি?"
আদিম ধরণের সম্পর্কে চিন্তা করুন u8: একটি বাইট অনুলিপি সহজ, কেবল একক বাইট অনুলিপি করুন, এবং একটি শব্দার্থক অনুলিপি ঠিক তত সহজ, একক বাইট অনুলিপি করুন। বিশেষ করে, একটি বাইট কপি হয় একটি শব্দার্থিক কপি ... মরচে এমনকি রয়েছে বিল্ট-ইন বৈশিষ্ট্যCopy যে যেমনটি কোন ধরনের অভিন্ন শব্দার্থিক এবং বাইট কপি আছে।
সুতরাং, এই Copyধরণের বাই-মান ব্যবহারগুলি স্বয়ংক্রিয়ভাবে শব্দার্থক অনুলিপিগুলিও তাই উত্সটি ব্যবহার করা চালিয়ে যাওয়া নিরাপদ।
let v: u8 = 1;
let w: u8 = v;
println!("{}", v);
পুরাতন : NoCopyচিহ্নিতকারীটি ধরণের Copy(যেমন কেবল আদিমদের সমষ্টি এবং &) যেগুলি হতে পারে তা ধরে নিয়ে সংযোজকটির স্বয়ংক্রিয় আচরণকে ওভাররাইড করে Copy। তবে অন্তর্নির্মিত বৈশিষ্ট্যগুলি অপ্ট-ইন করার সময় এটি পরিবর্তন হবে ।
উপরে উল্লিখিত হিসাবে, অন্তর্নির্মিত বৈশিষ্ট্যগুলি অপ্ট-ইন করা হয়, তাই সংকলকটির আর স্বয়ংক্রিয় আচরণ নেই। তবে অতীতে স্বয়ংক্রিয় আচরণের জন্য ব্যবহৃত বিধিটি প্রয়োগ করা বৈধ কিনা তা যাচাই করার জন্য একই নিয়ম Copy।