সি ++ এর পয়েন্টারে রেফারেন্সগুলি পাস করা


130

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

এটি আমি যা করছি:

void myfunc(string*& val)
{
    // Do stuff to the string pointer
}

// sometime later 
{
    // ...
    string s;
    myfunc(&s);
    // ...
}

এবং আমি এই ত্রুটি পাচ্ছি:

পরামিতি 1 কে 'স্টাড :: স্ট্রিং *' থেকে 'স্টাডি :: স্ট্রিং * ও' তে রূপান্তর করতে পারে না

উত্তর:


126

আপনার ফাংশন কলিং স্কোপটিতে কোনও প্রকৃত স্ট্রিং পয়েন্টারের রেফারেন্স আশা করে, কোনও বেনামে স্ট্রিং পয়েন্টার নয়। এভাবে:

string s;
string* _s = &s;
myfunc(_s);

ঠিক জরিমানা সংকলন করা উচিত।

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


86

সমস্যাটি হ'ল আপনি রেফারেন্সটির সাথে একটি অস্থায়ীভাবে বাঁধতে চেষ্টা করছেন, যা রেফারেন্স না থাকলে C ++ অনুমতি দেয় না const

সুতরাং আপনি নিম্নলিখিতগুলির মধ্যে একটি করতে পারেন:

void myfunc(string*& val)
{
    // Do stuff to the string pointer
}


void myfunc2(string* const& val)
{
    // Do stuff to the string pointer
}

int main()
// sometime later 
{
    // ...
    string s;
    string* ps = &s;

    myfunc( ps);   // OK because ps is not a temporary
    myfunc2( &s);  // OK because the parameter is a const&
    // ...

    return 0;
}

উদাহরণস্বরূপ string* const& valকম-সুসংগঠনের সমতুল্যের পরিবর্তে মিঃ বুড় উদাহরণ 2 নং পদ্ধতিতে যেভাবে লিখেছেন তা লেখার পক্ষে বিশেষভাবে শিক্ষণীয় const string* &val। আমার দৃষ্টিতে এটি স্পষ্টভাবে একটি রেখাযুক্ত রেফারেন্স , পয়েন্টারটির কাছে, একটি স্ট্রিংয়ের কাছে। সঠিকভাবে এই স্পষ্টতা পেতে আমি ব্যক্তিগতভাবে ঘোষণার T const&পরিবর্তে লেখার পছন্দ করি const T&
fish2000

1
নীট বাছাই (কোনও সমালোচনা নয়): আমার কাছে, bind a temporary to the referenceএই উত্তরে @ ক্রিসের চেয়ে এই উত্তরটি পরিষ্কার হয়েছে reference to an actual string pointer in the calling scope, not an anonymous string pointer। নির্বিশেষে, উভয়ই সম্ভবত আমার দৃষ্টিকোণ থেকে সঠিক।
কেভিনার্পে

1
@ fish2000 কেবল এটিই নয় const string*&এবং string* const&প্রকৃতপক্ষে বিভিন্ন ধরণের। প্রথমটি হ'ল একটি অ- constরেফারেন্স const string*, এবং দ্বিতীয়টি constএকটির রেফারেন্স string*
জাস্টিন সময় - মনিকা

@ ফিশ 2000 "প্রিফারিং" T const&থেকে সাবধান থাকুন const T&- @ জাস্টিন টাইম হিসাবে উল্লেখ করা হয়েছে যে তারা বিভিন্ন ধরণের। এটির কখনও কখনও কোনও পরিণতি নাও হতে পারে তবে অন্য পরিস্থিতিতে এটি একে অপরকে পছন্দ intকরা যেমন সমালোচিত হবে তেমনি পছন্দ করাও double
ওমটাই

3
@ ফিশ 2000 - একজন বলেছেন "এখানে এমন একটি রেফারেন্স রয়েছে যা আপনি এমন কিছুতে পরিবর্তন করতে পারবেন যা আপনি পরিবর্তন করতে পারবেন না" অন্যটি বলে "এখানে এমন একটি রেফারেন্স রয়েছে যা আপনি পরিবর্তন করতে পারবেন এমন কিছুতে পরিবর্তন করতে পারবেন না"। প্রদত্ত এই উদাহরণে, আপনি কেবল দু'জনের বিনিময় করতে পারবেন না।
ওমাতাই

10

এটিকে পরিবর্তন করুন:

  std::string s;
  std::string* pS = &s;
  myfunc(pS);

সম্পাদনা করুন:

এটিকে বলা হয় ref-to-pointerএবং আপনি কার্যকারিতা হিসাবে উল্লেখ হিসাবে অস্থায়ী ঠিকানা পাস করতে পারবেন না। (যদি না হয় const reference)

যদিও, আমি std::string* pS = &s;(একটি স্থানীয় ভেরিয়েবলের দিকে নির্দেশক) দেখিয়েছি , এর সাধারণ ব্যবহারটি হ'ল: আপনি যখন কলিটি পয়েন্টারটি নিজেই বদল করতে চান, তবে যে বস্তুটি এটি নির্দেশ করে তা নয়। উদাহরণস্বরূপ, একটি ফাংশন যা মেমোরি বরাদ্দ করে এবং মেমরি ব্লকের ঠিকানা বরাদ্দ করে যা এটি তার আর্গুমেন্টে বরাদ্দ করে তা অবশ্যই পয়েন্টারের একটি রেফারেন্স নিতে হবে, বা পয়েন্টারটিতে পয়েন্টার নিতে হবে:

void myfunc(string*& val)
{
//val is valid even after function call
   val = new std::string("Test");

}

5

&s স্ট্রিংয়ের জন্য অস্থায়ী পয়েন্টার উত্পাদন করে এবং আপনি অস্থায়ী বস্তুর রেফারেন্স করতে পারবেন না।


4
এটি একেবারেই সত্য নয় - আপনি অস্থায়ী স্থায়ীত্বের বিষয়ে একটি রেফারেন্স তৈরি করতে পারেন
1800 তথ্য

3

চেষ্টা করুন:

void myfunc(string& val)
{
    // Do stuff to the string pointer
}

// sometime later 
{
    // ...
    string s;
    myfunc(s);
    // ...
}

অথবা

void myfunc(string* val)
{
    // Do stuff to the string pointer
}

// sometime later 
{
    // ...
    string s;
    myfunc(&s);
    // ...
}

আমি যদিও যা করছি তার জন্য আমার পয়েন্টারের ঠিকানা এবং পয়েন্টার নিজেই প্রয়োজন। আমি মান দ্বারা পয়েন্টারটি পাস করতে চাই না।
অ্যালেক্স

তবুও বুঝতে পারছেন না আপনি কী অর্জন করার চেষ্টা করছেন। আপনার কাছে "স্ট্রিং এস" এর "পয়েন্টারের ঠিকানা" থাকতে পারে না, কেবল কারণ "স্ট্রিং এস" পয়েন্টার নয়।
অভিপ্রায়

@ অ্যালেক্স: আমি এটি গ্রহণ করেছি যে আপনি স্ট্রিং করছেন এমন স্ট্রিং অন্য যেটির সাথে সংরক্ষণ করা হচ্ছে ঠিক একইরকম এবং এটির বিষয়বস্তু একই রকম কিনা তাও আপনার সনাক্ত করা দরকার। যদি এটি হয় তবে নোট করুন যে আপনি কোনও রেফারেন্সের জন্য অ্যাড্রেস-অফ অপারেটরটি ব্যবহার করতে পারেন এবং এটি আপনাকে রেফারেন্সড অবজেক্টের ঠিকানা পাবেন: অকার্যকর f (std :: স্ট্রিং কনস্ট্যান্ডস) s স্টেড :: স্ট্রিং কনস্ট * পি = & গুলি; }
ডেভিড রদ্রিগেজ - ড্রিবিস

3

সম্পাদনা: আমি কিছু পরীক্ষা-নিরীক্ষা করেছি এবং আবিষ্কারকৃত জিনিসগুলি আমার ভাবনার চেয়ে কিছুটা সূক্ষ্ম। আমি এখন যা মনে করি তা হ'ল একটি সঠিক উত্তর।

&sকোনও মূল্য নেই তাই রেফারেন্সের ধরণটি উল্লেখ না করে আপনি এটিতে কোনও রেফারেন্স তৈরি করতে পারবেন না const। উদাহরণস্বরূপ, আপনি না করতে পারেন

string * &r = &s;

কিন্তু আপনি করতে পারেন

string * const &r = &s;

আপনি যদি ফাংশন শিরোনামে অনুরূপ ঘোষণা রাখেন তবে এটি কার্যকর হবে।

void myfunc(string * const &a) { ... }

অস্থায়ীতা নামে একটি আর সমস্যা আছে। নিয়মটি হ'ল আপনি যদি কোনও অস্থায়ী সম্পর্কে উল্লেখ করেন তবেই তাconst । সুতরাং এই ক্ষেত্রে কেউ তর্ক করতে পারে যে & গুলি একটি অস্থায়ী, এবং তাই constফাংশন প্রোটোটাইপ মধ্যে ঘোষণা করা আবশ্যক । ব্যবহারিক দৃষ্টিকোণ থেকে এটি এই ক্ষেত্রে কোনও পার্থক্য করে না। (এটি হয় কোনও মূল্যায়ন বা অস্থায়ী E যেভাবেই, একই নিয়ম প্রযোজ্য)) তবে কড়া কথায় বলতে গেলে, আমি মনে করি এটি সাময়িক নয় বরং একটি মূল্যবান। আমি ভাবছি দুজনের মধ্যে পার্থক্য করার কোনও উপায় আছে কিনা। (সম্ভবত এটি সহজেই সংজ্ঞায়িত করা হয়েছে যে সমস্ত অস্থায়ী মূল্যবোধগুলি মূল্যবান এবং সমস্ত অ-অমূল্যগুলি অস্থায়ী হয় I'm আমি মানক সম্পর্কে বিশেষজ্ঞ নই))

বলা হচ্ছে, আপনার সমস্যা সম্ভবত উচ্চতর স্তরের। আপনি কেন ঠিকানার রেফারেন্স চান s? আপনি যদি কোনও পয়েন্টারের রেফারেন্স চান তবে আপনাকে sপয়েন্টারটি হিসাবে হিসাবে সংজ্ঞায়িত করতে হবে

string *p = &s;
myfunc(p);

আপনি যদি কোনও রেফারেন্স sবা পয়েন্টার sচান তবে সোজা কাজটি করুন।


1

রুট নিরাপদ বাদে মুছে ফেলা বাইনারি গাছের সমস্ত পয়েন্টার তৈরি করতে আমি কেবলমাত্র একটি পয়েন্টারের রেফারেন্স ব্যবহার করেছি। পয়েন্টারটি নিরাপদ করতে আমাদের কেবল এটি 0 তে সেট করতে হবে আমি গাছটিকে মুছতে সক্ষম ফাংশনটি করতে পারি না (কেবল মূল রাখি) যেহেতু আমি প্রথম হিসাবে রুট (এই পয়েন্টার) ব্যবহার করছি বাম এবং ডানদিকে যেতে ইনপুট।

void BinTree::safe_tree(BinTree * &vertex ) {
    if ( vertex!=0 ) {  // base case
        safe_tree(vertex->left);    // left subtree.
            safe_tree(vertex->right);   //  right subtree.
          // delete vertex;  // using this delete causes an error, since they were deleted on the fly using inorder_LVR. If inorder_LVR does not perform delete to the nodes, then, use delete vertex;
        vertex=0;  // making a safe pointer
    }
} // end in

আনুষ্ঠানিক প্যারামিটারটি (এটি) পয়েন্টার হলে নীচের লাইন, একটি পয়েন্টারের একটি রেফারেন্স অবৈধ।


1

সি ++ 11 এবং মূলসূত্র উল্লেখগুলিতে আপনাকে স্বাগতম:

#include <cassert>
#include <string>

using std::string;

void myfunc(string*&& val)
{
    assert(&val);
    assert(val);
    assert(val->c_str());
    // Do stuff to the string pointer
}

// sometime later 
int main () {
    // ...
    string s;
    myfunc(&s);
    // ...
}

এখন আপনার পয়েন্টারের মান ( valযার দ্বারা উল্লেখ করা ) অ্যাক্সেস রয়েছে যা স্ট্রিংয়ের ঠিকানা।

আপনি পয়েন্টারটি সংশোধন করতে পারেন, এবং কেউ যত্ন নেবে না। এটি কোনও দিক যা প্রথম স্থানে থাকে তার একটি দিক।

সতর্কতা অবলম্বন করুন: পয়েন্টারের মানটি কেবল myfunc()রিটার্ন না হওয়া পর্যন্ত বৈধ । অবশেষে, এটি একটি অস্থায়ী।


-1

আমি জানি যে এটি পয়েন্টারগুলির রেফারেন্সগুলি পাস করার পক্ষে উপযুক্ত, আমি এটি গত সপ্তাহে করেছি, তবে সিনট্যাক্সটি কী ছিল তা আমি মনে করতে পারি না, কারণ আপনার কোডটি এখনই আমার মস্তিষ্কের সাথে সঠিক দেখাচ্ছে। তবে অন্য বিকল্পটি পয়েন্টারগুলির পয়েন্টার ব্যবহার করা হয়:

Myfunc(String** s)

-8

myfunc ("স্ট্রিং * এবং ভাল") এটি নিজেই কোনও অর্থ দেয় না। "স্ট্রিং * এবং ভাল" "স্ট্রিং ভাল" বোঝায়, * এবং একে অপরকে বাতিল করে দেয়। অবশেষে কেউ একটি ফাংশনে স্ট্রিং ভেরিয়েবল ("স্ট্রিং ভাল") পাস করতে পারে না। কেবলমাত্র প্রাথমিক তথ্য প্রকারগুলিকে কোনও ফাংশনে পাস করা যেতে পারে, অন্য ডেটা ধরণের জন্য পয়েন্টার বা রেফারেন্স হিসাবে পাস করতে হবে। কোনও ফাংশনে আপনার কাছে স্ট্রিং এবং ভাল বা স্ট্রিং * ভাল থাকতে পারে।


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