অকার্যকর * জন্য কোন বৈধ ব্যবহার আছে?


87

void*সি ++ এর বৈধ ব্যবহার আছে কি ? অথবা সি এর কারণে এটি চালু হয়েছিল?

শুধু আমার চিন্তা পুনরুদ্ধার করতে:

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

আউটপুট : আমি এমন কোনও পরিস্থিতির কথা ভাবতে পারি না যেখানে আমি void*পরিচিত বেস ক্লাস থেকে প্রাপ্ত কোনও কিছুর বিরোধিতা হিসাবে গ্রহণ করতে পছন্দ করব ।

কেবল আমার অর্থটি পরিষ্কার করার জন্য: আমি বিশেষভাবে জিজ্ঞাসা করছি না যে সেখানে কোনও ইউস-কেস void*রয়েছে কিনা, তবে যদি এমন কোনও মামলা থাকে যেখানে void*সেরা বা কেবল উপলভ্য পছন্দ থাকে। যার নিচে বেশ কিছু লোক সঠিকভাবে উত্তর দিয়েছে।


4
আপনি যখন int & std :: স্ট্রিংয়ের মতো একাধিক প্রকারের থাকতে চান তখন কেমন হবে?
আমির

12
@Amir, variant, any, বাঁধা ইউনিয়ন। যে কোনও কিছু যা আপনাকে প্রকৃত ধরণের সামগ্রী এবং ব্যবহারের জন্য নিরাপদ বলতে পারে।
রিভলবার_ওসেলোট

15
"সি এর আছে এটি" একটি শক্তিশালী ন্যায়সঙ্গততা, এর বেশি অনুসন্ধান করার দরকার নেই। এটি যথাসম্ভব এড়িয়ে যাওয়া উভয় ভাষায়ই ভাল জিনিস।
এন। 'সর্বনাম' মি।

4
জুট একটি জিনিস: সি স্টাইলের এপিআই এর সাথে ইন্টারপ করা এটিকে ছাড়াই বিশ্রী।
মার্টিন জেমস

4
পয়েন্টার ভেক্টরগুলির জন্য আকর্ষণীয় ব্যবহার হ'ল টাইপ ইরেজর
পাওলো এম

উত্তর:


81

void*অন্তত প্রয়োজনীয় ::operator new(প্রতিটি operator new...) এর ফলাফল mallocহিসাবে এবং প্লেসমেন্ট newঅপারেটরের যুক্তি হিসাবেও ।

void*প্রতিটি পয়েন্টার টাইপের সাধারণ সুপারটাইপ হিসাবে বিবেচনা করা যেতে পারে। সুতরাং এটি ঠিক পয়েন্টার অর্থ নয় void, কোনও কিছুতে পয়েন্টার।

BTW, যদি আপনি বিভিন্ন সম্পর্কহীন বিশ্বব্যাপী ভেরিয়েবলের জন্য কিছু ডেটা রাখতে চেয়েছিলেন, আপনি কিছু ব্যবহার করতে পারে std::map<void*,int> score; তাহলে থাকার ঘোষণা বিশ্বব্যাপী পর int x;এবং double y;এবং std::string s;না score[&x]=1;এবং score[&y]=2;এবংscore[&z]=3;

memset একটি void*ঠিকানা চায় (সর্বাধিক সাধারণ)

এছাড়াও, পসিক্স সিস্টেমে dlsym থাকে এবং এর রিটার্ন টাইপ স্পষ্টতই হওয়া উচিতvoid*


4
এটা খুব ভাল পয়েন্ট। আমি উল্লেখ করতে ভুলে গেছি যে আমি বাস্তবায়ন পক্ষের চেয়ে কোনও ভাষা ব্যবহারকারীর কাছ থেকে আরও বেশি চিন্তাভাবনা করেছি। আরও একটি জিনিস যদিও আমি বুঝতে পারি না: নতুন কোনও ফাংশন? আমি কীওয়ার্ড হিসাবে এটি আরও ভেবেছি
magu_

9
নতুন + এবং আকারের মতো একটি অপারেটর।
জোশুয়া

7
অবশ্যই একটি char *খুব মাধ্যমে স্মৃতি ফিরে আসতে পারে । তারা এই দিকটি খুব কাছাকাছি, যদিও অর্থ কিছুটা পৃথক।
edmz

@ জোশুয়া তা জানতেন না। আমাকে এই শেখানোর জন্য আপনাকে ধন্যবাদ। যেহেতু C++এই লিখিত হয় C++যথেষ্ট কারণ আছে void*। এই সাইটটি ভালবাসেন। একটি প্রশ্ন জিজ্ঞাসা অনেক শিখুন।
ম্যাগু_

4
@black পুরানো দিনের মধ্যে ফিরে যান, সি এমনকি করা হয়নি আছে একটি void*প্রকার। সমস্ত স্ট্যান্ডার্ড লাইব্রেরি ফাংশন ব্যবহৃতchar*
কোল জনসন

28

ব্যবহারের একাধিক কারণ রয়েছে void*, 3 অতি সাধারণ:

  1. void*এর ইন্টারফেস ব্যবহার করে একটি সি লাইব্রেরির সাথে আলাপচারিতা
  2. টাইপ-ইরেজোর
  3. অ-টাইপ করা মেমোরিটি বোঝায়

বিপরীত ক্রমে, (বা রূপগুলি) এর void*পরিবর্তে (3) দিয়ে টাইপযুক্ত মেমরিটি চিহ্নিত করা char*দুর্ঘটনাজনিত পয়েন্টার গাণিতিক প্রতিরোধে সহায়তা করে; খুব কম অপারেশন উপলব্ধ রয়েছে void*তাই এটি কার্যকর হওয়ার আগে সাধারণত কাস্টিং প্রয়োজন require এবং অবশ্যই, অনেকটা যেমন char*এলিয়াসিংয়ের সাথে কোনও সমস্যা নেই।

টাইপ-ইরেজোর (2) এখনও টেমপ্লেটগুলির সাথে একত্রে সি ++ এ ব্যবহৃত হয়:

  • নন-জেনেরিক কোড বাইনারি ব্লাট হ্রাস করতে সহায়তা করে, এটি জেনেরিক কোডেও শীতল পথে কার্যকর
  • জেনেরিক ধারক যেমন এমনকি কখনও কখনও স্টোরেজ জন্য জেনারিক কোড প্রয়োজনীয় std::function

এবং স্পষ্টতই, আপনি যখন ইন্টারফেসটি ব্যবহার করেন void*(1) তখন আপনার পছন্দ খুব কম থাকে।


15

হ্যাঁ. এমনকি সি ++ তেও আমরা কখনও কখনও এর void *পরিবর্তে চলে যাই template<class T*>কারণ কখনও কখনও টেমপ্লেট সম্প্রসারণের অতিরিক্ত কোডের ওজন অনেক বেশি।

সাধারণত আমি এটিকে প্রকৃত বাস্তবায়ন হিসাবে ব্যবহার করব এবং টেমপ্লেট টাইপটি এর উত্তরাধিকার সূত্রে প্রাপ্ত হবে এবং ক্যাসেটগুলি মোড়ানো করবে।

এছাড়াও, কাস্টম স্ল্যাব বরাদ্দকারীদের (অপারেটর নতুন বাস্তবায়ন) অবশ্যই ব্যবহার করতে হবে void *। এটি কারণগুলির মধ্যে একটি কারণ কেন g ++ পয়েন্টারকে অনুমতি মঞ্জুরির একটি এক্সটেনশান যুক্ত void *করেছিল যদিও এটি আকার 1 এর মতো।


আপনার উত্তর করার জন্য আপনাকে ধন্যবাদ। আপনি ঠিক বলেছেন আমি টেমপ্লেটগুলি উল্লেখ করতে ভুলে গেছি। কিন্তু টেমপ্লেট আরও ভাল কাজের জন্য যেহেতু খুব কমই একটি কর্মক্ষমতা শাস্তি পরিচয় করিয়ে উপযুক্ত হবে না (? Stackoverflow.com/questions/2442358/... )
magu_

4
টেমপ্লেটগুলি একটি কোড আকারের জরিমানা প্রবর্তন করে, এটি বেশিরভাগ ক্ষেত্রে পারফরম্যান্সের জরিমানাও।
জোশুয়া

struct wrapper_base {}; template<class T> struct wrapper : public wrapper_base {T val;} typedef wrapper* like_void_ptr;টেমপ্লেট ব্যবহার করে একটি ন্যূনতম শূন্য - * - সিমুলেটর।
ব্যবহারকারী 253751

4
@ জোশুয়া: আপনার "সর্বাধিক" জন্য একটি প্রশংসাপত্র প্রয়োজন হবে।
ব্যবহারকারী541686

@ মেহরদাদ: এল 1 ক্যাশে দেখুন।
জোশুয়া

10

ইনপুট: আমরা একাধিক ইনপুট ধরণের অনুমতি দিতে চাইলে আমরা ফাংশন এবং পদ্ধতিগুলি ওভারলোড করতে পারি

সত্য।

বিকল্পভাবে আমরা একটি সাধারণ বেস শ্রেণি সংজ্ঞায়িত করতে পারি।

এটি আংশিক সত্য: আপনি যদি একটি সাধারণ বেস শ্রেণি, একটি ইন্টারফেস বা অনুরূপ সংজ্ঞায়িত করতে না পারেন তবে কী হবে ? তাদের সংজ্ঞা দিতে আপনার সোর্স কোড অ্যাক্সেস থাকা দরকার, যা প্রায়শই সম্ভব হয় না।

আপনি টেম্পলেটগুলির উল্লেখ করেননি। যাইহোক, টেমপ্লেটগুলি পলিমারফিজমে আপনাকে সাহায্য করতে পারে না: এগুলি স্থির ধরণের সাথে কাজ করে অর্থাৎ সংকলনের সময় পরিচিত।

void*সর্বনিম্ন সাধারণ ডিনোমিনেটর হিসাবে বিবেচনা করা যেতে পারে। সি ++ তে সাধারণত আপনার এটির প্রয়োজন হয় না কারণ (i) আপনি সহজাতভাবে এটির সাথে বেশি কিছু করতে পারবেন না এবং (ii) প্রায় সবসময়ই আরও ভাল সমাধান পাওয়া যায়।

এমনকি আরও, আপনি সাধারণত এটি অন্য কংক্রিটের ধরণে রূপান্তর করে শেষ করবেন। এ কারণেই char *সাধারণত আরও ভাল, যদিও এটি সূচিত করে যে আপনি কোনও সি-স্টাইলের স্ট্রিং আশা করছেন, তথ্যের খাঁটি ব্লকের চেয়ে। এ কারণেই এর void*চেয়ে ভাল char*কারণ এটি অন্যান্য পয়েন্টার ধরণের থেকে অন্তর্ভুক্ত castালাইকে অনুমতি দেয়।

আপনার কিছু ডেটা পাওয়ার, এটির সাথে কাজ করার এবং একটি আউটপুট উত্পাদন করার কথা; এটি অর্জনের জন্য, আপনি যে ডেটা নিয়ে কাজ করছেন তা আপনার জানতে হবে, অন্যথায় আপনার আলাদা সমস্যা রয়েছে যা আপনি মূলত সমাধান করছেন না। অনেক ভাষায় নেইvoid*উদাহরণস্বরূপ, কোনও সমস্যা নেই এবং রয়েছে have

অন্য বৈধ ব্যবহার

যখন মতো কাজগুলির সঙ্গে পয়েন্টার অ্যাড্রেস মুদ্রণ printfপয়েন্টার থাকবে void*তাই ধরণ এবং, আপনার কাছে একটি ঢালাই প্রয়োজন হতে পারে void*


7

হ্যাঁ, এটি ভাষার যে কোনও জিনিস হিসাবে কার্যকর useful
উদাহরণস্বরূপ, আপনি কোনও শ্রেণীর প্রকারটি মুছে ফেলতে ব্যবহার করতে পারেন যা আপনি যখন প্রয়োজন হয় ঠিকঠাকভাবে সঠিক টাইপ করতে সক্ষম হন, যাতে ন্যূনতম এবং নমনীয় ইন্টারফেস থাকে।

ইন যে প্রতিক্রিয়া ব্যবহারের একটি উদাহরণ যে আপনি একটি ধারণা দিতে হবে না।
আমি স্বচ্ছতার জন্য এটি নীচে অনুলিপি এবং আটকান:

class Dispatcher {
    Dispatcher() { }

    template<class C, void(C::*M)() = C::receive>
    static void invoke(void *instance) {
        (static_cast<C*>(instance)->*M)();
    }

public:
    template<class C, void(C::*M)() = &C::receive>
    static Dispatcher create(C *instance) {
        Dispatcher d;
        d.fn = &invoke<C, M>;
        d.instance = instance;
        return d;
    }

    void operator()() {
        (fn)(instance);
    }

private:
    using Fn = void(*)(void *);
    Fn fn;
    void *instance;
};

স্পষ্টতই, এটি ব্যবহারগুলির একগুচ্ছ void*


4

একটি বহিরাগত গ্রন্থাগারের ক্রিয়াকলাপের সাথে ইন্টারফেস করা যা একটি পয়েন্টার দেয়। অ্যাডা অ্যাপ্লিকেশনটির জন্য এখানে একটি।

extern "C" { void* ada_function();}

void* m_status_ptr = ada_function();

এটি অ্যাডা আপনাকে যা জানাতে চেয়েছিল তা ফেরত দেয় returns আপনাকে এটিকে অভিনব কিছু করতে হবে না, আপনি এডাকে এটি পরবর্তী জিনিসটি ফেরত দিতে পারেন। আসলে সি ++ এ অ্যাডা পয়েন্টারকে ছিন্ন করা অ-তুচ্ছ বিষয়।


আমরা autoএই ক্ষেত্রে পরিবর্তে ব্যবহার করতে পারি না ? ধরে নিচ্ছি যে সংকলনের সময়টি টাইপটি পরিচিত।
ম্যাগু_

আহ, আজকাল আমরা সম্ভবত পারে। এই কোডটি কয়েক বছর আগে থেকে যখন আমি কিছু অ্যাডা র‌্যাপার তৈরি করেছি।
রেডসোনজা

অ্যাডা প্রকারগুলি শয়তান হতে পারে - এগুলি তাদের নিজস্ব করে তোলে, আপনি জানেন এবং এটিকে কৃপণ করে তুলতে একটি বিকৃত আনন্দ পান। আমাকে ইন্টারফেসটি পরিবর্তন করার অনুমতি দেওয়া হয়নি, এটি খুব সহজ হত এবং এটি সেই শূন্য পয়েন্টারগুলিতে লুকানো কিছু বাজে জিনিস ফিরিয়ে দেয়। উঃ
রেডসোনজা

2

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


mallocএবং newউভয়ই ফিরে আসে void *, সুতরাং আপনার প্রয়োজন হবে এমনকি যদি সি ++ তে কোনও অবজেক্ট শ্রেণি ছিল
দিমিত্রি গ্রিগরিয়েভ

যদি malloc বিধবা স্ত্রী, কিন্তু কঠোর ভাষায় নতুন বস্তু ফেরত পাঠাবেন *
nredko

আপনি কিভাবে পূর্ণসংখ্যার একটি অ্যারে বরাদ্দ করবেন?
দিমিত্রি গ্রিগরিয়েভ

@ দিমিত্রিগ্রিরিভ operator new()ফিরেছেন void *, তবে এই newঅভিব্যক্তিটি নেই
এমএম

1. আমি নই নিশ্চিত আমি একটি দেখতে চাই ভার্চুয়াল প্রতি বর্গ উপরে বেস বর্গ বস্তুর লিখুন সহ int2. যদি এটা অ ভার্চুয়াল EBC, তারপর কিভাবে এটি থেকে ভিন্ন void*?
লোরো

1

আমার মনে যে প্রথম জিনিসটি ঘটে (যা আমি সন্দেহ করি যা উপরের কয়েকটি উত্তরের একটি কংক্রিট কেস) উইন্ডোজের কোনও থ্রেডপ্রোকের কাছে কোনও বস্তুর উদাহরণ পাস করার সক্ষমতা।

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


0

একাধিক উত্তরাধিকারের ক্ষেত্রে, যদি কোনও বস্তুর দ্বারা দখলকৃত মেমরি খণ্ডের প্রথম বাইটে আপনাকে পয়েন্টার পেতে হয় তবে আপনি তা করতে dynamic_castপারেন void*

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