ইন্টারফেসে আমার কখন স্ট্রিং_ভিউ ব্যবহার করা উচিত?


16

আমি একটি অভ্যন্তরীণ লাইব্রেরি ব্যবহার করছি যা প্রস্তাবিত সি ++ গ্রন্থাগার নকল করার জন্য ডিজাইন করা হয়েছিল এবং গত কয়েক বছরে আমি দেখতে পেয়েছি এর ইন্টারফেসটি ব্যবহার থেকে পরিবর্তিত std::stringহয়েছে string_view

তাই আমি নতুন ইন্টারফেসের সাথে সঙ্গতিপূর্ণভাবে আমার কোডটি যথাযথভাবে পরিবর্তন করছি। দুর্ভাগ্যক্রমে, আমার যা পাস করতে হবে তা হল একটি স্টাডি :: স্ট্রিং প্যারামিটার এবং এমন একটি কিছু যা একটি স্ট্যান্ড :: স্ট্রিংয়ের ফেরতের মান value সুতরাং আমার কোডটি এরকম কিছু থেকে পরিবর্তিত হয়েছে:

void one_time_setup(const std::string & p1, int p2) {
   api_class api;
   api.setup (p1, special_number_to_string(p2));
}

প্রতি

void one_time_setup(const std::string & p1, int p2) {
   api_class api;
   const std::string p2_storage(special_number_to_string(p2));
   api.setup (string_view(&p1[0], p1.size()), string_view(&p2_storage[0], p2_storage.size()));
}

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

যাইহোক, এই পদ্ধতির পরামর্শটি আমি অন্য কোথাও দেখতে পাচ্ছি বলে মনে হচ্ছে উদাহরণস্বরূপ এই উত্তর :

অন্যদিকে, সি ++ 17 যেহেতু আপনার কোনও স্ট্যান্ড :: স্ট্রিং :: স্ট্রিং_ভিউয়ের পক্ষে হওয়া উচিত নয়:

আমি সেই পরামর্শটি অবাক করে দিয়েছি, যেহেতু এটি প্রাথমিকভাবে অপ্টিমাইজেশনের উদ্দেশ্যে, একটি কম নিরাপদ (মূলত গৌরবময় পয়েন্টার এবং দৈর্ঘ্য) দিয়ে তুলনামূলকভাবে নিরাপদ বস্তুর প্রতিস্থাপনের জন্য সর্বজনীনভাবে সমর্থন করে বলে মনে হচ্ছে।

সুতরাং যখন উচিত string_view ব্যবহার করা যেতে, এবং এটি না করা উচিত?


1
আপনাকে কখনই std::string_viewসরাসরি কনস্ট্রাক্টরকে কল করতে হবে না , আপনার সরাসরি স্ট্রিংগুলি std::string_viewসরাসরি পদ্ধতিতে নেওয়া উচিত এবং এটি স্বয়ংক্রিয়ভাবে রূপান্তরিত হবে।
ম্যাগজেজ

@ ম্যাগেজ - হুমম্ম। আমি (এখনও) একটি পূর্ণ-বর্ধিত সি ++ 17 সংকলক ব্যবহার করছি না, তাই সম্ভবত এটি বেশিরভাগ সমস্যা। এখনও, নমুনা কোড এখানে তার প্রয়োজন, যখন এক প্রকাশক অন্তত ইঙ্গিত করলো।
টেড

4
আমার উত্তরটি দেখুন রূপান্তর অপারেটর <string>শিরোনামে রয়েছে এবং স্বয়ংক্রিয়ভাবে ঘটে। এই কোডটি প্রতারণা এবং ভুল।
Mgetz

1
"স্বল্প সুরক্ষিত সহ" একটি স্ট্রিং রেফারেন্সের চেয়ে কোনও টুকরো কম সুরক্ষিত কীভাবে?
কোডসইনচওস

3
@ টেড কলার আপনার রেফারেন্সটিকে নির্দেশিত স্ট্রিংটিকে কেবল সহজেই মুক্ত করতে পারে যেহেতু তারা স্লাইসটি নির্দেশ করছে মেমরিটি মুক্ত করতে পারে।
কোডসইনচওস 21

উত্তর:


18
  1. মান গ্রহণের কার্যকারিতাটির কি স্ট্রিংয়ের মালিকানা নেওয়া দরকার? যদি তাই হয় std::string(নন-কনস্ট, নন-রেফ)। এই বিকল্পটি আপনাকে স্পষ্টভাবে একটি মানে স্থানান্তরিত করার পছন্দ দেয় পাশাপাশি যদি আপনি জানেন যে এটি কলিং প্রসঙ্গে আবার কখনও ব্যবহৃত হবে না।
  2. কার্যকারিতা কি কেবল স্ট্রিংটি পড়ে? যদি তাই হয় ব্যবহার std::string_view(const, অ-সুত্র) এই কারণ string_viewসব ব্যবস্থা করতে সক্ষম std::stringএবং char*ইস্যু ছাড়া একটি কপি না করে সহজে। এটি সমস্ত const std::string&পরামিতি প্রতিস্থাপন করা উচিত ।

পরিশেষে আপনি উচিত না ফোন করতে হবে std::string_viewকন্সট্রাকটর মত আপনি। std::stringএকটি রূপান্তর অপারেটর রয়েছে যা রূপান্তরটি স্বয়ংক্রিয়ভাবে পরিচালনা করে।


কেবল একটি বিষয় স্পষ্ট করার জন্য, আমি ভাবছি যে এই জাতীয় রূপান্তরকারী অপারেটর আজীবনের সবচেয়ে খারাপ সমস্যার জন্যও যত্ন নেবে, আপনার আর এইচএস স্ট্রিংয়ের মান কলটির পুরো দৈর্ঘ্যের জন্য থাকবে?
টেড

3
@ টেড আপনি যদি কেবল মানটি পড়ছেন তবে মানটি কলটি ছাড়িয়ে যাবে। আপনি যদি মালিকানা নিচ্ছেন তবে তারপরে কলটি ছাড়িয়ে নেওয়া দরকার। আমি কেন উভয় ক্ষেত্রে সম্বোধন করেছি। রূপান্তরকারী অপারেটর কেবল std::string_viewসহজতর করে ব্যবহার করা সহজলভ্য। যদি কোনও বিকাশকারী কোনও নিজস্ব পরিস্থিতিতে এটির ভুল ব্যবহার করে তবে এটি প্রোগ্রামিং ত্রুটি। std::string_viewকঠোরভাবে মালিকানাবিহীন।
মেটেজ

কেন const, non-ref? প্যারামিটার কনস্ট্যান্ট নির্দিষ্ট ব্যবহার পর্যন্ত, তবে সাধারণভাবে কন-কনস্টের হিসাবে যুক্তিসঙ্গত। এবং আপনি 3
s

const std::string_view &জায়গায় যাওয়ার সমস্যা কী const std::string &?
ceztko

@ceztko এটি সম্পূর্ণ অপ্রয়োজনীয় এবং ডেটা অ্যাক্সেস করার সময় একটি অতিরিক্ত নির্দেশিকা যুক্ত করে।
ম্যাজেজ

15

এ সি std::string_viewএর আরও কিছু সুবিধা নিয়ে আসে const char*: বিপরীতstd::string স্ট্রিং_ভিউ থেকে

  • স্মৃতির মালিক হয় না,
  • স্মৃতি বরাদ্দ করে না,
  • কিছু অফসেটে একটি বিদ্যমান স্ট্রিংয়ে নির্দেশ করতে পারে এবং
  • এর চেয়ে পয়েন্টার ইন্ডিরেশনের একটি কম স্তর রয়েছে std::string&

এর অর্থ একটি স্ট্রিং_ভিউ প্রায়শই অনুলিপিগুলি এড়াতে পারে, কাঁচা পয়েন্টারগুলির সাথে ডিল না করে।

আধুনিক কোডে, ফাংশন পরামিতিগুলির std::string_viewপ্রায় সমস্ত ব্যবহার প্রতিস্থাপন করা উচিত const std::string&। এটি একটি উত্স-সামঞ্জস্যপূর্ণ পরিবর্তন হওয়া উচিত, যেহেতু std::stringকোনও রূপান্তর অপারেটরকে এটি ঘোষণা করেstd::string_view

স্ট্রিং ভিউটি আপনার নির্দিষ্ট ব্যবহারের ক্ষেত্রে সহায়তা না করার কারণ যেখানে আপনাকে যেভাবেই স্ট্রিং তৈরি করতে হবে তার অর্থ এই নয় যে এটি সাধারণভাবে একটি খারাপ ধারণা। সি ++ স্ট্যান্ডার্ড গ্রন্থাগারটি সুবিধার পরিবর্তে সাধারণতার জন্য অনুকূলিত করা হয়েছে। "কম নিরাপদ" যুক্তিটি ধরে রাখে না, কারণ স্ট্রিং ভিউটি নিজেকে তৈরি করার প্রয়োজন হবে না।


2
এর বড় অসুবিধে std::string_viewহ'ল কোনও c_str()পদ্ধতির অনুপস্থিতি , ফলে অপ্রয়োজনীয়, মধ্যবর্তী std::stringবস্তুগুলি তৈরি করা এবং বরাদ্দ করা দরকার। এটি বিশেষত নিম্ন-স্তরের এপিআইগুলিতে সমস্যা।
ম্যাথিয়াস

1
@ মাথিয়াস এটি একটি ভাল বিষয়, তবে আমি মনে করি এটির বিশাল অপূর্ণতা নেই। একটি স্ট্রিং ভিউ আপনাকে কোনও অফসেটে বিদ্যমান স্ট্রিংয়ে নির্দেশ করতে দেয়। এই স্ট্রেরিং শূন্য-সমাপ্ত হতে পারে না, এর জন্য আপনার একটি অনুলিপি দরকার। স্ট্রিং ভিউ আপনাকে অনুলিপি তৈরি করতে বাধা দেয় না। এটি বহু স্ট্রিং প্রসেসিং টাস্কগুলিকে মঞ্জুরি দেয় যা পুনরাবৃত্তকারীদের সাথে সম্পাদন করা যায়। তবে আপনি ঠিক বলেছেন যে সিআই স্ট্রিং দরকার এমন এপিআইগুলি দর্শন থেকে লাভ করবে না। তারপরে একটি স্ট্রিং রেফারেন্স আরও উপযুক্ত হতে পারে।
আমন

@ মাথিয়াস, স্ট্রিং_ভিউ :: ডেটা () সি_স্ট্র্রি () এর সাথে মেলে না?
আইলিয়ান

3
@ জিভাকা সি সি স্ট্রিং শূন্য-সমাপ্ত হতে হবে তবে স্ট্রিং ভিউয়ের ডেটা সাধারণত শূন্য-সমাপ্ত হয় না কারণ এটি একটি বিদ্যমান স্ট্রিংকে নির্দেশ করে into উদাহরণস্বরূপ, যদি আমাদের স্ট্রিং abcdef\0এবং স্ট্রিং ভিউ থাকে যা cdeসাবস্ট্রিং এ নির্দেশ করে , এর পরে কোনও শূন্য অক্ষর নেই e- আসল স্ট্রিংটিতে একটি fথাকে। মান এছাড়াও নোট: "তথ্য () একটি বাফার যে নাল-সমাপ্ত নয় একটি পয়েন্টার ফেরত দিতে পারেন। অতএব এটি কোনও ফাংশনে ডেটা () প্রেরণ করা সাধারণত একটি ভুল যা কেবল একটি কনস্ট চার্ট * নেয় এবং নাল-টার্মিনেটেড স্ট্রিংয়ের প্রত্যাশা করে ”"
amon

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

8

আমি সেই পরামর্শটি অবাক করে দিয়েছি, যেহেতু এটি প্রাথমিকভাবে অপ্টিমাইজেশনের উদ্দেশ্যে, একটি কম নিরাপদ (মূলত গৌরবময় পয়েন্টার এবং দৈর্ঘ্য) দিয়ে তুলনামূলকভাবে নিরাপদ বস্তুর প্রতিস্থাপনের জন্য সর্বজনীনভাবে সমর্থন করে বলে মনে হচ্ছে।

আমি মনে করি এটি এর উদ্দেশ্যটিকে কিছুটা ভুল বুঝছে। এটি একটি "অপ্টিমাইজেশন" হওয়ার সময়, আপনি এটিকে ব্যবহার না করা থেকে নিজেকে সত্যবিচ্ছিন্ন হিসাবে ভাবতে হবে std::string

সি ++ এর ব্যবহারকারীরা কয়েক ডজন বিভিন্ন স্ট্রিং ক্লাস তৈরি করেছেন। স্থির দৈর্ঘ্যের স্ট্রিং ক্লাসগুলি, এসএসও-অনুকূলিত শ্রেণীর সাথে বাফার আকারটি একটি টেম্পলেট প্যারামিটার, স্ট্রিং ক্লাসগুলি যা তাদের তুলনা করতে ব্যবহৃত হ্যাশ মান সংরক্ষণ করে, ইত্যাদি Some কিছু লোক এমনকি COW- ভিত্তিক স্ট্রিং ব্যবহার করে। সি ++ প্রোগ্রামারদের যদি এমন একটি জিনিস করতে পছন্দ হয় তবে তা স্ট্রিং ক্লাস লিখতে পারে।

এবং এটি সি লাইব্রেরির মালিকানাধীন স্ট্রিংগুলিকে উপেক্ষা করে। নগ্ন char*গুলি, কিছু ধরণের আকারের সাথে।

সুতরাং আপনি যদি কিছু লাইব্রেরি লিখছেন, এবং আপনি একটি const std::string&নেন, ব্যবহারকারীকে এখন তারা যে স্ট্রিংটি ব্যবহার করছে তা নিতে হবে এবং এটিকে এটি অনুলিপি করতে হবে std::string। কয়েক ডজন।

আপনি যদি std::stringস্ট্রিং-নির্দিষ্ট ইন্টারফেসে অ্যাক্সেস চান তবে আপনার স্ট্রিংটি অনুলিপি করতে হবে কেন ? এ রকম অপচয়।

string_viewপ্যারামিটার হিসাবে গ্রহণ না করার মূল কারণগুলি হল:

  1. যদি আপনার চূড়ান্ত লক্ষ্যটি এমন একটি ইন্টারফেসে স্ট্রিংটি পৌঁছে দেয় যা কোনও NUL- সমাপ্ত স্ট্রিং ( fopenইত্যাদি) নেয়। std::stringNUL সমাপ্ত হওয়ার গ্যারান্টিযুক্ত; string_viewনয়। এবং কোনও ভিউ এটিকে এন-ইউএনএল-টার্মিনেটেড করার জন্য সাবস্ট্রিং করা খুব সহজ; উপ-স্ট্রিংিং একটি std::stringস্ট্রিংটিকে একটি NUL- সমাপ্ত পরিসীমাতে অনুলিপি করবে।

    এই দৃশ্যের জন্য আমি একটি বিশেষ NUL- টার্মিনেটেড স্ট্রিং_ভিউ স্টাইল টাইপ করেছি। আপনি বেশিরভাগ অপারেশন করতে পারেন, তবে এটির নয় যা এর NUL- সমাপ্ত স্থিতিটি (উদাহরণস্বরূপ শেষ থেকে ছাঁটা) break

  2. লাইফটাইম ইস্যু। আপনার যদি সত্যই এটি অনুলিপি করতে হয় std::stringবা অন্যথায় অক্ষরের অ্যারে ফাংশন কলকে আউটলাইভ করতে পারে তবে এটি গ্রহণ করে এই আপ-ফ্রন্টটি বলা ভাল const std::string &। অথবা std::stringএকটি মান প্যারামিটার হিসাবে একটি। এইভাবে, যদি তাদের কাছে ইতিমধ্যে এ জাতীয় স্ট্রিং থাকে, আপনি অবিলম্বে এর মালিকানা দাবি করতে পারেন, এবং কলার যদি তার অনুলিপিটি চারপাশে রাখার প্রয়োজন না হয় তবে তারা স্ট্রিংয়ের মধ্যে চলে যেতে পারেন।


এটা কি সত্য? আমি স্ট্যান্ডার্ড :: স্ট্রিংয়ের আগে সি ++ তে কেবলমাত্র স্ট্যান্ডার্ড ক্লাস সম্পর্কে অবগত ছিলাম। সি এর সাথে পশ্চাদপটে সামঞ্জস্যের জন্য চর * এর "স্ট্রিং" হিসাবে ব্যবহার করার জন্য কিছু সমর্থন রয়েছে, তবে আমার এটি ব্যবহার করার দরকার নেই। অবশ্যই, আপনি কল্পনা করতে পারেন এমন প্রায়শই ব্যবহারকারীর দ্বারা সংজ্ঞায়িত তৃতীয় পক্ষের ক্লাস রয়েছে এবং স্ট্রিংগুলি সম্ভবত এতে অন্তর্ভুক্ত রয়েছে, তবে আমার প্রায় কখনও সেগুলি ব্যবহার করতে হবে না।
টেড

@ টেড: আপনার "প্রায়শই কখনই সেগুলি ব্যবহার করতে হবে না" এর অর্থ এই নয় যে অন্য লোকেরা তাদের নিয়মিত ব্যবহার করে না। string_viewএকটি লিঙ্গুয়া ফ্রেঞ্চ টাইপ যা কোনও কিছুর সাথেই কাজ করতে পারে।
নিকল বোলাস

3
@ টেড: সেজন্য আমি "ভাষা / গ্রন্থাগার হিসাবে সি ++" এর বিপরীতে, "প্রোগ্রামিং পরিবেশ হিসাবে সি ++" বলেছি।
নিকোল বোলাস

2
@ টেড: " সুতরাং আমি সমানভাবে বলতে পারি" প্রোগ্রামিং পরিবেশ হিসাবে হাজার + টি ধারক ক্লাস রয়েছে তাই "সি ++"? "এবং এটি রয়েছে। তবে আমি পুনরাবৃত্তকারীদের সাথে কাজ করে এমন আলগোরিদিম লিখতে পারি এবং যে দৃষ্টান্ত অনুসরণ করে কোনও ধারক ক্লাস তাদের সাথে কাজ করবে। বিপরীতে, "অ্যালগরিদম" যে কোনও অক্ষরের অক্ষরকে নিতে পারে তা লেখার পক্ষে অনেক কঠিন ছিল। সহ string_view, এটি সহজ।
নিকল বোলাস

1
@ টেড: চরিত্রের অ্যারেগুলি একটি খুব বিশেষ কেস। এগুলি অত্যন্ত সাধারণ এবং সংলগ্ন চরিত্রগুলির বিভিন্ন ধারকগুলি কেবল কীভাবে তাদের মেমরি পরিচালনা করে তা নয়, আপনি কীভাবে ডেটা জুড়ে পুনরাবৃত্তি করেন তা নয়। সুতরাং একটি একক লিঙ্গুয়া ফ্র্যাঙ্কা পরিসীমা ধরণের যা কোনও টেমপ্লেট নিয়োগ না করেই এই জাতীয় সমস্ত মামলা কভার করতে পারে তা বোঝা যায়। এর বাইরে সাধারণীকরণ হ'ল রেঞ্জ টিএস এবং টেম্পলেটগুলির প্রদেশ।
নিকল বোলাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.