টাইপ পেনিং থিমের পার্থক্য: স্থানটিতে তুচ্ছ নির্মাণ


9

আমি জানি এটি একটি দুর্দান্ত সাধারণ বিষয়, তবে সাধারণ ইউবি যতটা খুঁজে পাওয়া সহজ, আমি এখনও এই রূপটি খুঁজে পাইনি।

সুতরাং, আমি তথ্যের অনুলিপি এড়িয়ে গিয়ে পিক্সেল অবজেক্টগুলিকে আনুষ্ঠানিকভাবে পরিচয় করানোর চেষ্টা করছি।

এটা কি বৈধ?

struct Pixel {
    uint8_t red;
    uint8_t green;
    uint8_t blue;
    uint8_t alpha;
};

static_assert(std::is_trivial_v<Pixel>);

Pixel* promote(std::byte* data, std::size_t count)
{
    Pixel * const result = reinterpret_cast<Pixel*>(data);
    while (count-- > 0) {
        new (data) Pixel{
            std::to_integer<uint8_t>(data[0]),
            std::to_integer<uint8_t>(data[1]),
            std::to_integer<uint8_t>(data[2]),
            std::to_integer<uint8_t>(data[3])
        };
        data += sizeof(Pixel);
    }
    return result; // throw in a std::launder? I believe it is not mandatory here.
}

প্রত্যাশিত ব্যবহারের প্যাটার্ন, খুব সহজসাধ্য:

std::byte * buffer = getSomeImageData();
auto pixels = promote(buffer, 800*600);
// manipulate pixel data

আরো নির্দিষ্টভাবে:

  • এই কোডটি কি সঠিকভাবে সংজ্ঞায়িত আচরণ করে?
  • যদি হ্যাঁ, এটি কি ফিরে আসা পয়েন্টারটি ব্যবহার করা নিরাপদ করে?
  • যদি হ্যাঁ, অন্য কোন Pixelধরণের ক্ষেত্রে এটি বাড়ানো যেতে পারে? (কেবলমাত্র 3 টি উপাদানযুক্ত পিক্সেলটি কী_ট্রিভিয়াল সীমাবদ্ধতা শিথিল করা হচ্ছে?)

ঝনঝন এবং জিসিসি উভয়ই পুরো লুপটিকে নির্লজ্জের জন্য অনুকূলিত করে, যা আমি চাই। এখন, আমি এটি জানতে চাই যে এটি কিছু সি ++ বিধি লঙ্ঘন করে কিনা।

আপনি যদি এটির সাথে চারপাশে খেলতে চান তবে গডবোল্ট লিঙ্ক

(দ্রষ্টব্য: সত্ত্বেও আমি সি ++ 17 ট্যাগ করিনি std::byte, কারণ প্রশ্নটি ব্যবহার করে রাখে char)


2
তবে কনটেগিউজ Pixelএস নতুন রাখা এখনও Pixelএস এর অ্যারে নয় not
জারোড 42

1
@ স্পেকট্রা যেগুলি যদিও অ্যারে করে না। আপনার একে অপরের পাশে পিক্সেল অবজেক্টের গুচ্ছ রয়েছে। এটি একটি অ্যারের থেকে পৃথক।
নাথান অলিভার

1
তো না আপনি কোথায় করেন pixels[some_index]বা করেন *(pixels + something)? তা হবে ইউবি।
নাথান অলিভার

1
প্রাসঙ্গিক বিভাগটি এখানে এবং মূল বাক্যাংশটি হ'ল পি যদি একটি অ্যারে অবজেক্ট x এর অ্যারের এলিমেন্টকে নির্দেশ করে । এখানে pixels(পি) অ্যারে অবজেক্টের জন্য পয়েন্টার নয়, তবে একটি একক পয়েন্টার Pixel। এর অর্থ আপনি কেবল pixels[0]আইনীভাবে অ্যাক্সেস করতে পারবেন ।
নাথান অলিভার

3
আপনি wg21.link/P0593 পড়তে চান ।
ইকামত্মর

উত্তর:


3

promoteঅ্যারের হিসাবে ফলাফলটি ব্যবহার করা এটি অপরিজ্ঞাত আচরণ । আমরা যদি [এক্সপিআরএডিডি] / ৪.২ এর দিকে লক্ষ্য করি তবে আমাদের কাছে আছে

অন্যথায়, যদি Pএকটি অ্যারের উপাদান পয়েন্ট iএকটি অ্যারের বস্তুরx সঙ্গে nউপাদানের ([dcl.array]), এক্সপ্রেশন P + Jএবং J + P(যেখানে Jমূল্য আছে j) (সম্ভবত-প্রকল্পিত) অ্যারে উপাদানে বিন্দু i+jএর xযদি 0≤i+j≤nএবং অভিব্যক্তি P - Jপয়েন্ট ( সম্ভবত-প্রকল্পিত) অ্যারের উপাদান i−jএর xযদি 0≤i−j≤n

আমরা দেখতে পাই যে এটির জন্য বিন্যাসটির প্রয়োজন হয় অ্যারে অবজেক্টের দিকে actually যদিও আপনার কাছে আসলে অ্যারে অবজেক্ট নেই। আপনার একটি সিঙ্গেলের একটি পয়েন্টার রয়েছে Pixelযা কেবল Pixelsএটির সাথে অনুসরণযোগ্য স্মৃতিতে অনুসরণ করে। তার মানে আপনি যে একমাত্র উপাদানটি অ্যাক্সেস করতে পারবেন তা হ'ল প্রথম উপাদান। অন্য যে কোনও কিছু অ্যাক্সেস করার চেষ্টা করা অপরিজ্ঞাত আচরণ হবে কারণ আপনি পয়েন্টারের জন্য বৈধ ডোমেনের শেষ পেরিয়ে গেছেন।


দ্রুত তা খুঁজে বের করার জন্য ধন্যবাদ। আমি অনুমান করার পরিবর্তে আমি একটি পুনরাবৃত্তি তৈরি করব। সাইডেনোট হিসাবে, এর অর্থ &somevector[0] + 1হ'ল ইউবি (ভাল, আমি বলতে চাইছি ফলাফল পয়েন্টারটি ব্যবহার করা হবে)।
দর্শকদের

@ স্পেকট্রাস আসলে এটি ঠিক আছে। আপনি সর্বদা একটি বস্তুর অতীততে পয়েন্টারটি পেতে পারেন। আপনি যদি কেবলমাত্র সেই পয়েন্টারটিকে অবজ্ঞা করতে পারেন না, এমনকি সেখানে কোনও বৈধ অবজেক্ট থাকলেও।
নাথান অলিভার

হ্যাঁ, আমি নিজেকে আরও পরিষ্কার করার জন্য মন্তব্যটি সম্পাদনা করেছি, আমি বোঝাতে পেরেছি ফলাফলটি পয়েন্টারটিকে ডিফারেন্স করা হয়েছে :) নিশ্চিত করার জন্য ধন্যবাদ।
14:44

@ স্পেকট্রা কোন সমস্যা নেই। সি ++ এর এই অংশটি খুব কঠিন হতে পারে। যদিও হার্ডওয়ারটি আমাদের এটি করতে চায় তা করবে, এটি আসলে কোডিং ছিল না। আমরা সি ++ বিমূর্ত মেশিনে কোডিং করছি এবং এটি একটি ব্যাস্তব্যক্তি মেশিন;) আশা করি P0593 গৃহীত হবে এবং এটি আরও সহজ হয়ে উঠবে।
নাথান অলিভার

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

1

আপনার কাছে ইতিমধ্যে প্রত্যাবর্তিত পয়েন্টারটির সীমিত ব্যবহার সম্পর্কিত একটি উত্তর রয়েছে তবে আমি যুক্ত করতে চাই যে আমি এটিও মনে করি যে std::launderআপনাকে এমনকি প্রথমটিতে অ্যাক্সেস করতে সক্ষম হওয়া প্রয়োজন Pixel:

reinterpret_castআগে কোনো সম্পন্ন করা হয় Pixelবস্তুর নির্মিত হয় (অভিমানী আপনি এমনটি না getSomeImageData)। সুতরাং reinterpret_castপয়েন্টার মান পরিবর্তন করবে না। ফলস্বরূপ পয়েন্টারটি এখনও std::byteফাংশনে পাস করা অ্যারের প্রথম উপাদানটির দিকে নির্দেশ করবে ।

আপনি যখন Pixelবস্তুগুলি তৈরি করেন , সেগুলি অ্যারের মধ্যে বাসা বাঁধেstd::byte এবং অ্যারেগুলি অবজেক্টগুলির জন্য স্টোরেজ সরবরাহstd::byte করবে ।Pixel

এমন কিছু ক্ষেত্রে রয়েছে যেখানে স্টোরেজের পুনঃব্যবহারের কারণে পুরানো অবজেক্টের একটি পয়েন্টার স্বয়ংক্রিয়ভাবে নতুন বস্তুর দিকে নির্দেশিত হয়। তবে এটি এখানে যা ঘটছে তা নয়, তাই resultএখনও std::byteঅবজেক্টটির দিকে নির্দেশ করবে Pixel। আমার ধারণা এটি ব্যবহার করে যেমন এটি কোনও Pixelবস্তুর দিকে ইঙ্গিত করছে প্রযুক্তিগতভাবে অনির্ধারিত আচরণ হতে চলেছে।

আমি মনে করি যে এটি এখনও অবধি ধারণ করে, আপনি যদি বস্তুটি reinterpret_castতৈরির পরেও করেন তবে Pixelযেহেতু Pixelবস্তু এবং std::byteএটির জন্য সঞ্চয়স্থান সরবরাহ করে তা পয়েন্টার-আন্তঃ রূপান্তরযোগ্য নয় । তারপরেও পয়েন্টারটি অবজেক্টের দিকে std::byteনয়, বরং পয়েন্টারটি নির্দেশ করবে Pixel

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


এছাড়াও আপনাকে নিশ্চিত করতে হবে যে std::byteপয়েন্টারটি যথাযথভাবে সংযুক্ত করা হয়েছে Pixelএবং অ্যারেটি যথেষ্ট পরিমাণে বড়। যতদূর আমি মনে করি স্ট্যান্ডার্ডটির সত্যই প্রয়োজন হয় না Pixelযেটির মতো একই প্রান্তিককরণ রয়েছে std::byteবা এটির প্যাডিং নেই।


এছাড়াও এর Pixelকোনওটিই তুচ্ছ বা সত্যিকার অর্থে এর অন্য কোনও সম্পত্তির উপর নির্ভর করে । std::byteঅ্যারে পর্যাপ্ত আকারের এবং Pixelঅবজেক্টগুলির জন্য উপযুক্তভাবে সংযুক্ত থাকাকালীন সবকিছুই একইভাবে আচরণ করবে ।


আমি বিশ্বাস করি যে এটি সঠিক। এমনকি যদি অ্যারে জিনিসটি (অযোগ্যতা std::vector) কোনও সমস্যা নাও std::launderহয়ে থাকে তবে প্লেসমেন্ট-এর newযেকোনটি অ্যাক্সেস করার আগে আপনাকে ফলাফলের প্রয়োজন হবে Pixel। এখনই, std::launderএখানে ইউবি রয়েছে, যেহেতু সংলগ্ন Pixelগুলি লন্ডারড পয়েন্টার থেকে পৌঁছতে পারে ।
ফিউরিয়েশ

@ ফিউরিশ আমি নিশ্চিত নই যে ফিরে আসার আগে std::launderযদি আবেদন করা হয় তবে কেন ইউবি হবে result। সংলগ্ন Pixel"নয় পৌঁছানো ধুতে পয়েন্টার আমার বুঝতে দ্বারা যাচ্ছে মাধ্যমে" eel.is/c++draft/ptr.launder#4 । এমনকি এটি আমি কীভাবে এটি ইউবি হয় তা দেখতে পাচ্ছি না, কারণ পুরো মূল std::byteঅ্যারেটি মূল পয়েন্টার থেকে পৌঁছতে পারে
আখরোট

পরেরটি পয়েন্টার Pixelথেকে পৌঁছনীয় নয় std::byte, তবে এটি launderএড পয়েন্টার থেকে। আমি বিশ্বাস করি এটি এখানে প্রাসঙ্গিক। আমি সংশোধন করে খুশি, যদিও।
ফিউরিশ

@ ফিউরিশ যা আমি বলতে পারি তা থেকে এখানে প্রদত্ত উদাহরণগুলির কোনওটি প্রয়োগ হয় না এবং প্রয়োজনীয়তার সংজ্ঞাটিও মান হিসাবে একই বলে না। পুনঃব্যবহারযোগ্যতা স্টোরের বাইটের ক্ষেত্রে সংজ্ঞায়িত করা হয়, বস্তু নয়। পরবর্তী দ্বারা দখল করা বাইটটি Pixelমূল পয়েন্টার থেকে আমার কাছে পৌঁছনীয় বলে মনে হয়, কারণ মূল পয়েন্টারটি std::byteঅ্যারের একটি উপাদানকে নির্দেশ করে যা Pixel"তৈরির জন্য স্টোরেজ তৈরির বাইট রয়েছে " বা অবিলম্বে ঘেরযুক্ত অ্যারের মধ্যে যা জেড একটি উপাদান "শর্ত প্রয়োগ করে (যেখানে Zরয়েছে Y, তেমনি std::byteউপাদানটি নিজেই)।
আখরোট

আমি মনে করি যে পরবর্তী স্টোরেজ বাইটগুলি Pixelলন্ডার্ড পয়েন্টারের মাধ্যমে পৌঁছতে পারে না যদিও পয়েন্ট-টু Pixelঅবজেক্ট কোনও অ্যারে অবজেক্টের উপাদান নয় এবং অন্য কোনও প্রাসঙ্গিক বস্তুর সাথে পয়েন্টার-আন্তঃ পরিবর্তনযোগ্যও নয়। তবে আমি এই std::launderগভীরতার মধ্যে প্রথমবারের এই বিশদটি সম্পর্কেও ভাবছি । আমি এটি সম্পর্কে 100% নিশ্চিত নই।
আখরোট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.