স্ট্যান্ড :: মুভ এবং এসটিডি :: ফরোয়ার্ডের মধ্যে পার্থক্য কী?


160

আমি এটি এখানে দেখেছি: মুভ কনস্ট্রাক্টর কলিং বেস-ক্লাস মুভ কনস্ট্রাক্টর

কেউ ব্যাখ্যা করতে পারে:

  1. মধ্যে পার্থক্য std::moveএবং std::forward, বিশেষ করে কিছু কোড উদাহরণ?
  2. এটি সম্পর্কে সহজে কীভাবে ভাববেন এবং কখন ব্যবহার করবেন


"সহজেই এটি সম্পর্কে কীভাবে ভাববেন এবং কখন কোনটি ব্যবহার করবেন" আপনি moveযখন কোনও মান সরিয়ে নিতে চান এবং forwardকখন আপনি নিখুঁত ফরোয়ার্ডিং ব্যবহার করতে চান তা ব্যবহার করেন। এটি এখানে রকেট বিজ্ঞান নয়;)
নিকল বোলাস

সরানো () শর্তহীন নিক্ষেপ সঞ্চালন যেখানে এগিয়ে হিসাবে () পেরিয়ে গেছে যে পরামিতি উপর ভিত্তি করে কাস্ট সঞ্চালন।
রাগা__এম

উত্তর:


159

std::moveএকটি অবজেক্ট নেয় এবং আপনাকে এটি একটি অস্থায়ী (মূল্য) হিসাবে বিবেচনা করে। যদিও এটি কোনও অর্থগত প্রয়োজন নয়, সাধারণত কোনও মূল্যের কোনও রেফারেন্স গ্রহণ করা কোনও ফাংশন এটিকে অবৈধ করে দেবে। আপনি যখন দেখবেন std::move, এটি ইঙ্গিত করে যে অবজেক্টের মান পরে ব্যবহার করা উচিত নয়, তবে আপনি এখনও একটি নতুন মান নির্ধারণ করতে পারেন এবং এটি ব্যবহার চালিয়ে যেতে পারেন।

std::forwardএকক ব্যবহারের কেস রয়েছে: কলকারী এটি পাস করার জন্য ব্যবহৃত মান শ্রেণিতে (মূল্য বা মূল্য) একটি টেম্প্লেটেড ফাংশন প্যারামিটার (ফাংশনের অভ্যন্তরে) castালাইয়ের জন্য। এটি "যথাযথ ফরওয়ার্ডিং" নামে একটি স্কিমকে যথাযথ আর্গুমেন্টকে যথাযথ হিসাবে প্রেরণ করতে এবং লভ্যালুগুলিকে লভ্যালু হিসাবে প্রেরণ করতে দেয়।

করতে চিত্রিত :

void overloaded( int const &arg ) { std::cout << "by lvalue\n"; }
void overloaded( int && arg ) { std::cout << "by rvalue\n"; }

template< typename t >
/* "t &&" with "t" being template param is special, and  adjusts "t" to be
   (for example) "int &" or non-ref "int" so std::forward knows what to do. */
void forwarding( t && arg ) {
    std::cout << "via std::forward: ";
    overloaded( std::forward< t >( arg ) );
    std::cout << "via std::move: ";
    overloaded( std::move( arg ) ); // conceptually this would invalidate arg
    std::cout << "by simple passing: ";
    overloaded( arg );
}

int main() {
    std::cout << "initial caller passes rvalue:\n";
    forwarding( 5 );
    std::cout << "initial caller passes lvalue:\n";
    int x = 5;
    forwarding( x );
}

হাওয়ার্ড যেমন উল্লেখ করেছেন, তেমন মিল রয়েছে যেমন এই দুটি ফাংশনই কেবল রেফারেন্স টাইপের জন্য .ালাই। তবে এই নির্দিষ্ট ব্যবহারের ক্ষেত্রে (যা মূল্যের রেফারেন্স কাস্টগুলির উপযোগের 99.9% কভার করে) এর বাইরে আপনার static_castসরাসরি ব্যবহার করা উচিত এবং আপনি কী করছেন তার একটি ভাল ব্যাখ্যা লিখতে হবে।


আমি নই নিশ্চিত করুন যে এটি সঠিক যে std::forwardএর শুধুমাত্র ব্যবহারের ক্ষেত্রে ফাংশন আর্গুমেন্ট এর নিখুঁত ফরওয়ার্ডিং হয়। আমি এমন পরিস্থিতিতে পড়েছি যেখানে আমি অবজেক্টের সদস্যদের মতো অন্যান্য জিনিসগুলিও পুরোপুরি এগিয়ে নিতে চাই।
জিফ রোমার

@ জিফআমার একটি প্যারামিটারের সদস্য? আপনার কি উদাহরণ আছে?
পোটোসওয়টার

আমি পৃথক প্রশ্ন হিসাবে একটি উদাহরণ পোস্ট করেছি: স্ট্যাকওভারফ্লো
জেফ রোমার

হুম, সুতরাং যদি আমি এটি সঠিকভাবে বুঝতে পারি তবে এর অর্থ হ'ল আমি একটি একক ফাংশন ফরোয়ার্ড () লিখতে পারি যেখানে এগিয়ে (5) 5 এ পরিচালনা করে যেমন আমি এটির মান দিয়ে পাস করেছি যেখানে ফরোয়ার্ড (এক্স) এক্সের উপর চালিত হয় যেন আমি এটি পাস করেছি স্পষ্টভাবে একটি ওভারলোড না লিখে রেফারেন্স।
ইহানেই

@ আইহানেই হ্যাঁ, এটাই ধারণা! তবে এটি একটি সাধারণ ফাংশন নয়, একটি টেমপ্লেট হতে হবে।
পোটোটোভটার

63

উভয় std::forwardএবং std::moveকাস্ট ব্যতীত কিছুই নয়।

X x;
std::move(x);

উপরের এক্সটি xটাইপের এক্সের লভালিউ এক্সপ্রেশনটি টাইপ এক্সের একটি মূল্যবোধকে প্রকাশ করে (সঠিক হওয়ার জন্য একটি মূল্য)। moveএকটি মূল্যও গ্রহণ করতে পারে:

std::move(make_X());

এবং এক্ষেত্রে এটি একটি পরিচয় ফাংশন: এক্স টাইপের এক্সের একটি মূল্যায়ন নেয় এবং প্রকার এক্সের একটি মূল্য দেয় returns

এর মাধ্যমে std::forwardআপনি কিছুটা গন্তব্য নির্বাচন করতে পারেন:

X x;
std::forward<Y>(x);

xটাইপ এক্স এর লভ্যালু এক্সপ্রেশনটি ওয়াই টাইপের এক্সপ্রেশনকে কাস্ট করে Y

ওয়াই এক্স একজন প্রবেশযোগ্য বেস, বা এক্স ওয়াই একটি বেজ একটি রেফারেন্স হতে পারে এক্স, অথবা এক্স ওয়ান একটি রেফারেন্স সঙ্গে CV-কোয়ালিফায়ার দূরে নিক্ষেপ করতে পারবে না হতে পারে forward, কিন্তু এক CV-কোয়ালিফায়ার যোগ করতে পারেন। অ্যাক্সেসযোগ্য বেস রূপান্তরকরণ ব্যতীত Y এমন ধরণের হতে পারে না যা এক্স থেকে কেবল রূপান্তরযোগ্য।

যদি Y একটি লভ্যালু রেফারেন্স হয় তবে ফলাফলটি একটি লভ্যালু এক্সপ্রেশন হবে। যদি Y কোনও লভ্যালু রেফারেন্স না হয় তবে ফলাফলটি একটি মূল্য (সুনির্দিষ্ট হওয়ার জন্য xvalue) এক্সপ্রেশন হবে।

forwardY যদি লভ্যালু রেফারেন্স না হয় তবেই একটি মূল্যের যুক্তি নিতে পারে। এটি হল, আপনি লভ্যালুতে কোনও মূল্যায়ন নিক্ষেপ করতে পারবেন না। এটি সুরক্ষার কারণেই এটি কারণ সাধারণত এটি ঝুঁকির উল্লেখগুলিতে বাড়ে। তবে মূল্যের সাথে কোনও মূল্যকে castালাই ঠিক আছে এবং অনুমোদিত।

আপনি যদি ওয়াইকে এমন কিছু নির্দিষ্ট করার চেষ্টা করেন যা অনুমোদিত নয়, ত্রুটিটি সংকলন সময়ে ধরা হবে, রান সময় নয়।


আমি যদি কোনও ফাংশনটি ব্যবহার করে কোনও জিনিসকে পুরোপুরি ফরোয়ার্ড করি std::forward, তবে সেই ফাংশনটি কার্যকর হওয়ার পরে, আমি কি সেই অবজেক্টটি ব্যবহার করতে পারি? আমি সচেতন যে ক্ষেত্রে std::moveএটি একটি সংজ্ঞায়িত আচরণ।
iammilind

1
সংক্রান্ত move: stackoverflow.com/a/7028318/576911 জন্য forward, যদি আপনি একটি lvalue মধ্যে পাস, আপনার এপিআই যেমন যদি এটা একটি lvalue পায় প্রতিক্রিয়া করা উচিত নয়। সাধারণত এর অর্থ হল মানটি সংশোধিত হবে। তবে এটি যদি কোনও অবিশ্বাস্য লভ্যালু হয় তবে আপনার এপিআই এটি পরিবর্তন করেছে। আপনি একটি rvalue মধ্যে পাস হলে, এই স্বাভাবিকভাবে আপনার এপিআই তা থেকে সরানো হয়েছে, এবং এইভাবে মানে stackoverflow.com/a/7028318/576911 প্রয়োগ করবে।
হাওয়ার্ড হিন্যান্ট

21

std::forwardপ্যারামিটারটি ঠিক ঠিক যেভাবে কোনও ফাংশনে প্রেরণ করা হয়েছিল তা এগিয়ে দেওয়ার জন্য ব্যবহৃত হয় । ঠিক এখানে প্রদর্শিত:

যুক্তি ফরোয়ার্ড করার জন্য কখন std :: ব্যবহার করবেন?

ব্যবহার std::moveঅফার, একটি rvalue যেমন একটি বস্তু সম্ভবত একটি পদক্ষেপ কন্সট্রাকটর বা ফাংশন rvalues গ্রহণ মেলে। এটি নিজে থেকে কোনও মূল্যায়ন না std::move(x)হলেও এটি করে x

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.