কনস্ট্রেশন রেফারেন্স দ্বারা ডিফল্ট আর্গুমেন্টের মানটি ফিরিয়ে দেওয়া ঠিক কি?


26

নীচের উদাহরণগুলির মতো স্থির রেফারেন্স দ্বারা ডিফল্ট আর্গুমেন্টের মানটি ফেরত দেওয়া ঠিক হবে:

https://coliru.stacked-crooked.com/a/ff76e060a007723b

#include <string>

const std::string& foo(const std::string& s = std::string(""))
{
    return s;
}

int main()
{
    const std::string& s1 = foo();
    std::string s2 = foo();

    const std::string& s3 = foo("s");
    std::string s4 = foo("s");
}

3
সাধারণ পরীক্ষা: std::stringআপনার নিজের শ্রেণীর সাথে প্রতিস্থাপন করুন যাতে আপনি নির্মাণ এবং ধ্বংস ট্র্যাক করতে পারেন।
ব্যবহারকারী 4581301

1
@ user4581301 যদি ক্রমটি সঠিক হয় তবে এটি প্রমাণ করে না যে নির্মাণটি যদিও ঠিক আছে।
পিটার - মনিকা পুনরায়

6
@ ব্যবহারকারী 4581301 "যখন আমি এটি চেষ্টা করেছি তখন এটি কাজ হয়েছিল"
অপরিজ্ঞাত

এটি লক্ষ করা উচিত যে প্রশ্নটি তার কথার মধ্যে বিভ্রান্তিমূলক একটি id কনস্ট রেফারেন্সের মাধ্যমে আপনি কোনও ডিফল্ট আর্গুমেন্টের মান ফিরিয়ে দিচ্ছেন না, তবে আপনি কনস্টের রেফারেন্সের (... একটি ডিফল্ট আর্গুমেন্টে) কনস্টের রেফারেন্স ফিরিয়ে দিচ্ছেন।
দামন

2
@ হিরজয়েবব এই বিবৃতিটির সাথে 100% সম্মত হন, তবে আপনি যে প্রসঙ্গে এটি ব্যবহার করছেন তা নয় not আমি এই প্রশ্নটি যেভাবে পড়ছি তার সমাধান "অবজেক্টের জীবনকাল কখন শেষ?" ডেস্ট্রাক্টর যখন ডাকা হয় তখন তা খুঁজে বের করা ভাল উপায়। একটি অটোমেটিক ভেরিয়েবলের জন্য ডেস্ট্রাক্টরকে ঠিক সময়ে কল করা উচিত বা আপনার বড় সমস্যা হয়েছে।
ব্যবহারকারী 4581301

উত্তর:


18

আপনার কোডগুলিতে s1এবং উভয়ই s3রেফারেন্সগুলি জড়িত। s2এবং s4ঠিক আছে।

প্রথম কলটিতে, std::stringডিফল্ট আর্গুমেন্ট থেকে তৈরি অস্থায়ী শূন্য বস্তুটি কল সম্বলিত অভিব্যক্তির প্রসঙ্গে তৈরি করা হবে। সুতরাং, এটি সংজ্ঞায়নের শেষে মারা যাবে s1, যা s1ঝাঁকুনী ছেড়ে যায় ।

দ্বিতীয় কলে, অস্থায়ী std::stringবস্তুটি আরম্ভ করার জন্য ব্যবহৃত হয় s2, তারপরে এটি মারা যায়।

তৃতীয় কলটিতে, স্ট্রিং আক্ষরিক "s"একটি অস্থায়ী std::stringবস্তু তৈরি করতে ব্যবহৃত হয় এবং এটি সংজ্ঞা s3ছাড়াই, মারা যাওয়ার পরেও মারা যায়s3 আনত।

চতুর্থ কলে, std::stringমান সহ অস্থায়ী বস্তুটি "s"আরম্ভ করার জন্য ব্যবহৃত হয় s4এবং তারপরে এটি মারা যায়।

সি ++ 17 দেখুন [শ্রেণী.কালীন] / 6.1

একটি ফাংশন কলে (8.2.2) রেফারেন্স প্যারামিটারে আবদ্ধ একটি অস্থায়ী বস্তু কলযুক্ত পূর্ণ-এক্সপ্রেশন সমাপ্ত না হওয়া অবধি স্থায়ী থাকে।


1
উত্তরের আকর্ষণীয় অংশটি হ'ল এই আহ্বান যে কলারের প্রসঙ্গে ডিফল্ট যুক্তি তৈরি করা হবে। এটি গিলিয়ামের স্ট্যান্ডার্ড উক্তি দ্বারা সমর্থিত বলে মনে হচ্ছে।
পিটার - মনিকা পুনরায়

2
@ পিটার-রেইনস্টেটমোনিকা দেখুন [expr.call] / 4, "... প্রতিটি প্যারামিটারের আরম্ভ এবং ধ্বংস কলিং ফাংশনের প্রসঙ্গেই ঘটে ..."
ব্রায়ান

8

এটি নিরাপদ নয় :

সাধারণভাবে, একটি অস্থায়ী জীবনকাল "" এটি পাস করে "আরও বাড়ানো যায় না: একটি দ্বিতীয় রেফারেন্স, যা অস্থায়ীভাবে আবদ্ধ ছিল সেই রেফারেন্স থেকে আরম্ভ করা তার জীবনকালকে প্রভাবিত করে না।


সুতরাং আপনি কী std::string s2 = foo();বৈধ বলে মনে করেন (সর্বোপরি, কোনও রেফারেন্স স্পষ্টভাবে প্রেরণ করা হয়নি)?
পিটার - মনিকা পুনরায় স্থাপন করুন

1
@ পিটার-রেইনস্টেটমোনিকা যে নতুন বস্তুটি নির্মিত হবে সে হিসাবে এটি নিরাপদ। আমার উত্তরটি কেবল আজীবন প্রসার সম্পর্কে। অন্য দুটি উত্তর ইতিমধ্যে সবকিছু আবৃত। আমি আমার মধ্যে পুনরাবৃত্তি হবে না।
বিভ্রান্তি

5

এটি স্ট্রিংয়ের পরে কী করবে তার উপর নির্ভর করে।

আপনার প্রশ্নটি যদি আমার কোডটি সঠিক হয়? তাহলে হ্যাঁ

থেকে [dcl.fct.default] / 2

[ উদাহরণ : ঘোষণা

void point(int = 3, int = 4);

শূন্য, এক, বা টাইপ ইন্টের দুটি আর্গুমেন্ট সহ কল ​​করা যেতে পারে এমন একটি ফাংশন ঘোষণা করে। এটি যেকোন উপায়ে বলা যেতে পারে:

point(1,2);  point(1);  point();

শেষ দুটি কল সমান point(1,4)এবংpoint(3,4) যথাক্রমে । - শেষ উদাহরণ ]

সুতরাং আপনার কোড কার্যকরভাবে এর সমতুল্য:

const std::string& s1 = foo(std::string(""));
std::string s2 = foo(std::string(""));

আপনার সমস্ত কোড সঠিক, তবে এই ক্ষেত্রে কোনও ক্ষেত্রে রেফারেন্সের আজীবন এক্সটেনশন নেই, যেহেতু রিটার্নের ধরণটি একটি রেফারেন্স।

যেহেতু আপনি কোনও অস্থায়ী সাথে কোনও ফাংশনটি কল করেন, ফিরে আসা স্ট্রিংয়ের আজীবন বিবৃতিটি প্রসারিত করে না।

const std::string& s1 = foo(std::string("")); // okay

s1; // not okay, s1 is dead. s1 is the temporary.

আপনার উদাহরণটি s2ঠিক আছে যেহেতু আপনি সেটমেন্ট শেষ হওয়ার আগে অস্থায়ী থেকে অনুলিপি করেছেন (বা সরানো)। s3তুলনায় একই সমস্যা আছে s1

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