সি ++ টিপল বনাম স্ট্রাক্ট


96

std::tupleকেবলমাত্র এবং কেবলমাত্র একটি ডেটা ব্যবহারের মধ্যে কোনও পার্থক্য রয়েছে struct?

typedef std::tuple<int, double, bool> foo_t;

struct bar_t {
    int id;
    double value;
    bool dirty;
}

আমি অনলাইনে যা পেয়েছি তা থেকে, আমি দেখতে পেলাম যে দুটি প্রধান পার্থক্য রয়েছে: এটি structআরও বেশি পঠনযোগ্য, অন্যদিকে tupleঅনেকগুলি জেনেরিক ফাংশন ব্যবহার করা যেতে পারে। পারফরম্যান্সের কোনও উল্লেখযোগ্য পার্থক্য থাকতে হবে? এছাড়াও, ডেটা বিন্যাসটি একে অপরের সাথে সামঞ্জস্যপূর্ণ (আদান-প্রদানের সাথে কাস্ট করা)?


আমি কেবল মন্তব্য করেছি আমি কাস্ট প্রশ্ন সম্পর্কে ভুলে গিয়েছিলাম : বাস্তবায়নটি tupleবাস্তবায়ন সংজ্ঞায়িত হয়, সুতরাং এটি আপনার বাস্তবায়নের উপর নির্ভর করে। ব্যক্তিগতভাবে, আমি এটি বিশ্বাস করব না
ম্যাথিউ এম।

উত্তর:


32

টুপল এবং স্ট্রাক্ট সম্পর্কে আমাদের একই আলোচনা রয়েছে এবং আমি টুপল এবং স্ট্রাক্টের মধ্যে পারফরম্যান্সের মেয়াদে পার্থক্য সনাক্ত করতে আমার এক সহকর্মীর সাহায্যে কিছু সাধারণ বেঞ্চমার্ক লিখি। আমরা প্রথমে একটি ডিফল্ট কাঠামো এবং একটি টিপল দিয়ে শুরু করি।

struct StructData {
    int X;
    int Y;
    double Cost;
    std::string Label;

    bool operator==(const StructData &rhs) {
        return std::tie(X,Y,Cost, Label) == std::tie(rhs.X, rhs.Y, rhs.Cost, rhs.Label);
    }

    bool operator<(const StructData &rhs) {
        return X < rhs.X || (X == rhs.X && (Y < rhs.Y || (Y == rhs.Y && (Cost < rhs.Cost || (Cost == rhs.Cost && Label < rhs.Label)))));
    }
};

using TupleData = std::tuple<int, int, double, std::string>;

তারপরে আমরা আমাদের সহজ স্ট্রাক্ট এবং টিউপলের পারফরম্যান্সের তুলনা করার জন্য সেলোরো ব্যবহার করি। নীচে gcc-4.9.2 এবং ঝনঝন -০.০ ব্যবহার করে সংগৃহীত বেঞ্চমার্ক কোড এবং পারফরম্যান্স ফলাফল রয়েছে:

std::vector<StructData> test_struct_data(const size_t N) {
    std::vector<StructData> data(N);
    std::transform(data.begin(), data.end(), data.begin(), [N](auto item) {
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<> dis(0, N);
        item.X = dis(gen);
        item.Y = dis(gen);
        item.Cost = item.X * item.Y;
        item.Label = std::to_string(item.Cost);
        return item;
    });
    return data;
}

std::vector<TupleData> test_tuple_data(const std::vector<StructData> &input) {
    std::vector<TupleData> data(input.size());
    std::transform(input.cbegin(), input.cend(), data.begin(),
                   [](auto item) { return std::tie(item.X, item.Y, item.Cost, item.Label); });
    return data;
}

constexpr int NumberOfSamples = 10;
constexpr int NumberOfIterations = 5;
constexpr size_t N = 1000000;
auto const sdata = test_struct_data(N);
auto const tdata = test_tuple_data(sdata);

CELERO_MAIN

BASELINE(Sort, struct, NumberOfSamples, NumberOfIterations) {
    std::vector<StructData> data(sdata.begin(), sdata.end());
    std::sort(data.begin(), data.end());
    // print(data);

}

BENCHMARK(Sort, tuple, NumberOfSamples, NumberOfIterations) {
    std::vector<TupleData> data(tdata.begin(), tdata.end());
    std::sort(data.begin(), data.end());
    // print(data);
}

ঝনঝন -০.০.০ এর সাথে সংগৃহীত পারফরম্যান্স ফলাফল

Celero
Timer resolution: 0.001000 us
-----------------------------------------------------------------------------------------------------------------------------------------------
     Group      |   Experiment    |   Prob. Space   |     Samples     |   Iterations    |    Baseline     |  us/Iteration   | Iterations/sec  | 
-----------------------------------------------------------------------------------------------------------------------------------------------
Sort            | struct          | Null            |              10 |               5 |         1.00000 |    196663.40000 |            5.08 | 
Sort            | tuple           | Null            |              10 |               5 |         0.92471 |    181857.20000 |            5.50 | 
Complete.

এবং gcc-4.9.2 ব্যবহার করে কর্মক্ষমতা ফলাফল সংগ্রহ করা

Celero
Timer resolution: 0.001000 us
-----------------------------------------------------------------------------------------------------------------------------------------------
     Group      |   Experiment    |   Prob. Space   |     Samples     |   Iterations    |    Baseline     |  us/Iteration   | Iterations/sec  | 
-----------------------------------------------------------------------------------------------------------------------------------------------
Sort            | struct          | Null            |              10 |               5 |         1.00000 |    219096.00000 |            4.56 | 
Sort            | tuple           | Null            |              10 |               5 |         0.91463 |    200391.80000 |            4.99 | 
Complete.

উপরের ফলাফলগুলি থেকে আমরা পরিষ্কারভাবে দেখতে পাচ্ছি

  • টিপল একটি ডিফল্ট কাঠামোর চেয়ে দ্রুত

  • ঝাঁকুনির মাধ্যমে বাইনারি উত্পাদনের সিসিএসের তুলনায় উচ্চতর পারফরম্যান্স রয়েছে। ঝনঝন-বনাম-জিসিসি এই আলোচনার উদ্দেশ্য নয় তাই আমি বিশদে ডুব দেব না।

আমরা সকলেই জানি যে প্রতিটি একক কাঠামোর সংজ্ঞার জন্য একটি == বা <বা> অপারেটর লেখা বেদনাদায়ক এবং বগী কাজ হবে। এসটিডি :: টাই ব্যবহার করে আমাদের কাস্টম তুলকটি প্রতিস্থাপন করুন এবং আমাদের বেনমার্কটি পুনরায় চালু করুন।

bool operator<(const StructData &rhs) {
    return std::tie(X,Y,Cost, Label) < std::tie(rhs.X, rhs.Y, rhs.Cost, rhs.Label);
}

Celero
Timer resolution: 0.001000 us
-----------------------------------------------------------------------------------------------------------------------------------------------
     Group      |   Experiment    |   Prob. Space   |     Samples     |   Iterations    |    Baseline     |  us/Iteration   | Iterations/sec  | 
-----------------------------------------------------------------------------------------------------------------------------------------------
Sort            | struct          | Null            |              10 |               5 |         1.00000 |    200508.20000 |            4.99 | 
Sort            | tuple           | Null            |              10 |               5 |         0.90033 |    180523.80000 |            5.54 | 
Complete.

এখন আমরা দেখতে পাচ্ছি যে std :: টাই ব্যবহার করা আমাদের কোডটিকে আরও মার্জিত করে তোলে এবং ভুল করা শক্ত হয় তবে যাইহোক, আমরা প্রায় 1% পারফরম্যান্স ছেড়ে দেব। আমি এখনই স্ট্যান্ড :: টাইয়ের সমাধানের সাথে থাকব কারণ আমি কাস্টমাইজড তুলনাকারীর সাথে ভাসমান পয়েন্ট সংখ্যা তুলনা করার বিষয়ে একটি সতর্কতাও পেয়েছি।

এখনও অবধি আমাদের স্ট্রাক্ট কোডটি দ্রুত চালানোর জন্য আমাদের কোনও সমাধান হয়নি। অদলবদল ফাংশনটি একবার দেখে নেওয়া যাক এবং আমরা কোনও কার্য সম্পাদন করতে পারি কিনা তা দেখতে এটি আবার লিখুন:

struct StructData {
    int X;
    int Y;
    double Cost;
    std::string Label;

    bool operator==(const StructData &rhs) {
        return std::tie(X,Y,Cost, Label) == std::tie(rhs.X, rhs.Y, rhs.Cost, rhs.Label);
    }

    void swap(StructData & other)
    {
        std::swap(X, other.X);
        std::swap(Y, other.Y);
        std::swap(Cost, other.Cost);
        std::swap(Label, other.Label);
    }  

    bool operator<(const StructData &rhs) {
        return std::tie(X,Y,Cost, Label) < std::tie(rhs.X, rhs.Y, rhs.Cost, rhs.Label);
    }
};

ঝনঝন -০.০.০ ব্যবহার করে পারফরম্যান্স ফলাফল

Celero
Timer resolution: 0.001000 us
-----------------------------------------------------------------------------------------------------------------------------------------------
     Group      |   Experiment    |   Prob. Space   |     Samples     |   Iterations    |    Baseline     |  us/Iteration   | Iterations/sec  | 
-----------------------------------------------------------------------------------------------------------------------------------------------
Sort            | struct          | Null            |              10 |               5 |         1.00000 |    176308.80000 |            5.67 | 
Sort            | tuple           | Null            |              10 |               5 |         1.02699 |    181067.60000 |            5.52 | 
Complete.

এবং gcc-4.9.2 ব্যবহার করে কর্মক্ষমতা ফলাফল সংগ্রহ করা

Celero
Timer resolution: 0.001000 us
-----------------------------------------------------------------------------------------------------------------------------------------------
     Group      |   Experiment    |   Prob. Space   |     Samples     |   Iterations    |    Baseline     |  us/Iteration   | Iterations/sec  | 
-----------------------------------------------------------------------------------------------------------------------------------------------
Sort            | struct          | Null            |              10 |               5 |         1.00000 |    198844.80000 |            5.03 | 
Sort            | tuple           | Null            |              10 |               5 |         1.00601 |    200039.80000 |            5.00 | 
Complete.

এখন আমাদের স্ট্রাক্টটি এখন টিউপলের তুলনায় কিছুটা দ্রুত (প্রায় 3% ঝনঝন করে এবং জিসিসি সহ 1% এর কম) তবে যাইহোক, আমাদের সমস্ত স্ট্রাকের জন্য আমাদের কাস্টমাইজড অদলবদল ফাংশনটি লেখার দরকার নেই।


24

আপনি যদি আপনার কোডটিতে বিভিন্ন আলাদা টিপল ব্যবহার করেন তবে আপনি যে পরিমাণ ফান্টর ব্যবহার করছেন তা ঘনীভূত করে আপনি পালিয়ে যেতে পারেন। আমি এটি বলি কারণ আমি প্রায়শই নিম্নলিখিত ফর্মগুলি ব্যবহার করেছি:

template<int N>
struct tuple_less{
    template<typename Tuple>
    bool operator()(const Tuple& aLeft, const Tuple& aRight) const{
        typedef typename boost::tuples::element<N, Tuple>::type value_type;
        BOOST_CONCEPT_REQUIRES((boost::LessThanComparable<value_type>));

        return boost::tuples::get<N>(aLeft) < boost::tuples::get<N>(aRight);
    }
};

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

স্বাভাবিকভাবেই, আপনি যদি টুপল পথে যেতে যাচ্ছেন তবে তাদের সাথে কাজ করার জন্য আপনাকে এনাম তৈরি করতে হবে:

typedef boost::tuples::tuple<double,double,double> JackPot;
enum JackPotIndex{
    MAX_POT,
    CURRENT_POT,
    MIN_POT
};

এবং বুম, আপনার কোড সম্পূর্ণ পঠনযোগ্য:

double guessWhatThisIs = boost::tuples::get<CURRENT_POT>(someJackPotTuple);

কারণ আপনি নিজের মধ্যে থাকা আইটেমগুলি পেতে চাইলে এটি নিজের বর্ণনা করে।


8
আহ ... সি ++ এর ফাংশন পয়েন্টার রয়েছে, তাই template <typename C, typename T, T C::*> struct struct_less { template <typename C> bool operator()(C const&, C const&) const; };এটি সম্ভব হওয়া উচিত। এটির বানানটি কিছুটা কম সুবিধাজনক তবে এটি কেবল একবার লেখা।
ম্যাথিউ মিঃ

17

টিপল ডিফল্টরূপে তৈরি করেছে (== এবং! = এর জন্য এটি প্রতিটি উপাদানের সাথে <। <= ... তুলনা করে, প্রথমে তুলনা করে, যদি একই সাথে দ্বিতীয়টি তুলনা করা হয় ...) তুলনামূলক: http://en.cppreferences.com/w/ সিপিপি / ইউটিলিটি / টিপল / অপারেটর_সিএমপি

সম্পাদনা করুন: মন্তব্যটিতে উল্লিখিত হিসাবে সি ++ ২০ স্পেসশিপ অপারেটর আপনাকে কোডটির একটি (কদর্য, তবে এখনও একটি মাত্র) লাইন দিয়ে এই কার্যকারিতাটি নির্দিষ্ট করার একটি উপায় দেয়।


4
সি ++ ২০ এ, স্পেসশিপ অপারেটরটি ব্যবহার করে এটি ন্যূনতম বয়লারপ্লেটের সাথে প্রতিকার করে ।
জন ম্যাকফার্লেন

6

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

ডিফল্ট 'রিলিজ' সেটিংস ব্যবহার করে আমার মেশিনে এটি VS2015CE এর সাথে চালানো থেকে সাধারণ ফলাফল:

Structs took 0.0814905 seconds.
Tuples took 0.282463 seconds.

আপনি সন্তুষ্ট না হওয়া পর্যন্ত এটি সঙ্গে বানর করুন।

#include <iostream>
#include <string>
#include <tuple>
#include <vector>
#include <random>
#include <chrono>
#include <algorithm>

class Timer {
public:
  Timer() { reset(); }
  void reset() { start = now(); }

  double getElapsedSeconds() {
    std::chrono::duration<double> seconds = now() - start;
    return seconds.count();
  }

private:
  static std::chrono::time_point<std::chrono::high_resolution_clock> now() {
    return std::chrono::high_resolution_clock::now();
  }

  std::chrono::time_point<std::chrono::high_resolution_clock> start;

};

struct ST {
  int X;
  int Y;
  double Cost;
  std::string Label;

  bool operator==(const ST &rhs) {
    return
      (X == rhs.X) &&
      (Y == rhs.Y) &&
      (Cost == rhs.Cost) &&
      (Label == rhs.Label);
  }

  bool operator<(const ST &rhs) {
    if(X > rhs.X) { return false; }
    if(Y > rhs.Y) { return false; }
    if(Cost > rhs.Cost) { return false; }
    if(Label >= rhs.Label) { return false; }
    return true;
  }
};

using TP = std::tuple<int, int, double, std::string>;

std::pair<std::vector<ST>, std::vector<TP>> generate() {
  std::mt19937 mt(std::random_device{}());
  std::uniform_int_distribution<int> dist;

  constexpr size_t SZ = 1000000;

  std::pair<std::vector<ST>, std::vector<TP>> p;
  auto& s = p.first;
  auto& d = p.second;
  s.reserve(SZ);
  d.reserve(SZ);

  for(size_t i = 0; i < SZ; i++) {
    s.emplace_back();
    auto& sb = s.back();
    sb.X = dist(mt);
    sb.Y = dist(mt);
    sb.Cost = sb.X * sb.Y;
    sb.Label = std::to_string(sb.Cost);

    d.emplace_back(std::tie(sb.X, sb.Y, sb.Cost, sb.Label));
  }

  return p;
}

int main() {
  Timer timer;

  auto p = generate();
  auto& structs = p.first;
  auto& tuples = p.second;

  timer.reset();
  std::sort(structs.begin(), structs.end());
  double stSecs = timer.getElapsedSeconds();

  timer.reset();
  std::sort(tuples.begin(), tuples.end());
  double tpSecs = timer.getElapsedSeconds();

  std::cout << "Structs took " << stSecs << " seconds.\nTuples took " << tpSecs << " seconds.\n";

  std::cin.get();
}

এর জন্য ধন্যবাদ. আমি লক্ষ্য করেছি যে, যখন সঙ্গে অপ্টিমাইজ -O3, tuplesকম সময় নেয় structs
সিমোগ

3

ঠিক আছে, একটি পিওডি স্ট্রাক্ট প্রায়শই (আব) নিম্ন স্তরের সংক্ষিপ্ত খণ্ড পড়া এবং সিরিয়ালাইজেশনে ব্যবহৃত হতে পারে। একটি টিপল কিছু পরিস্থিতিতে আরও অনুকূলিত হতে পারে এবং আরও ফাংশন সমর্থন করে, যেমনটি আপনি বলেছেন।

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


3

"জেনেরিক ফাংশন" যতদূর যায়, বুস্ট.ফিউশন কিছুটা ভালবাসার দাবি রাখে ... এবং বিশেষত BOOST_FUSION_ADAPT_STRUCT

পৃষ্ঠাটি থেকে ছিটকে পড়া : অ্যাব্র্যাকডব্রা

namespace demo
{
    struct employee
    {
        std::string name;
        int age;
    };
}

// demo::employee is now a Fusion sequence
BOOST_FUSION_ADAPT_STRUCT(
    demo::employee
    (std::string, name)
    (int, age))

এর অর্থ হ'ল সমস্ত ফিউশন অ্যালগরিদম এখন স্ট্রাক্টের জন্য প্রযোজ্য demo::employee


সম্পাদনা : পারফরম্যান্স পার্থক্য বা লেআউট সামঞ্জস্যতা সম্পর্কিত, tupleএর লেআউট বাস্তবায়ন সংজ্ঞায়িত তাই সামঞ্জস্যপূর্ণ নয় (এবং এইভাবে আপনি উভয় উপস্থাপনের মধ্যে নিক্ষেপ করা উচিত নয়) এবং সাধারণভাবে আমি কোন পার্থক্য কর্মক্ষমতা অনুযায়ী আশা করতে হবে (কমপক্ষে প্রকাশে) ধন্যবাদ ধন্যবাদ ইনলাইনিং get<N>


16
আমি বিশ্বাস করি না যে এটিই সর্বোচ্চ ভোট দেওয়া উত্তর। এটি এমনকি প্রশ্নের উত্তর দেয় না। প্রশ্নটি tupleএস এবং structএস সম্পর্কে , উত্সাহ নয়!
gsamaras

@ জি.সমারাস: প্রশ্নটি টিউপলসের মধ্যে পার্থক্য structএবং বিশেষত আলগরিদমগুলির প্রাচুর্য সম্পর্কে স্টুডের সাথে সামঞ্জস্য করার জন্য অ্যালগরিদমগুলির অনুপস্থিতি (তার ক্ষেত্রগুলিতে পুনরাবৃত্তি দিয়ে শুরু করে) এর সাথে টিউপসগুলিতে হস্তক্ষেপ করতে হয়। এই উত্তরটি দেখায় যে বুস্ট.ফিউশন ব্যবহার করে এই ফাঁকটি ব্রিজ করা যেতে পারে, টিউপসগুলিতে রয়েছে যতগুলি structঅ্যালগরিদম রয়েছে। আমি জিজ্ঞাসা করা ঠিক দুটি প্রশ্নের উপর একটি ছোট ব্লার্ব যুক্ত করেছি।
ম্যাথিউ এম।

3

এছাড়াও, ডেটা বিন্যাসটি একে অপরের সাথে সামঞ্জস্যপূর্ণ (আদান-প্রদানের সাথে কাস্ট করা)?

অদ্ভুতভাবে আমি প্রশ্নের এই অংশে সরাসরি প্রতিক্রিয়া দেখতে পাচ্ছি না।

উত্তর: না । বা কমপক্ষে নির্ভরযোগ্যভাবে নয়, কারণ টিপলের বিন্যাসটি অনির্দিষ্ট।

প্রথমত, আপনার স্ট্রাক্ট একটি স্ট্যান্ডার্ড লেআউট প্রকার । সদস্যদের অর্ডারিং, প্যাডিং এবং প্রান্তিককরণ মান এবং আপনার প্ল্যাটফর্ম এবিআইয়ের সংমিশ্রণ দ্বারা ভালভাবে সংজ্ঞায়িত করা হয়েছে।

যদি একটি টিউপল একটি মান বিন্যাসের ধরণ ছিল এবং আমরা জানতাম যে ক্ষেত্রগুলি প্রকারগুলি নির্দিষ্ট ক্রমে নির্দিষ্ট করা হয়েছে তবে আমাদের কিছুটা আস্থা থাকতে পারে যা এটি কাঠামোর সাথে মেলে।

টিপলটি সাধারণত উত্তরাধিকার ব্যবহার করে প্রয়োগ করা হয়, দুটি পদ্ধতির একটিতে: পুরানো লোকী / আধুনিক সি ++ ডিজাইন পুনরাবৃত্ত শৈলী, বা আরও নতুন ভেরিয়ডিক স্টাইল। উভয়ই কোনও স্ট্যান্ডার্ড লেআউট প্রকার নয়, কারণ উভয়ই নিম্নলিখিত শর্তগুলি লঙ্ঘন করে:

  1. (সি ++ এর আগে)

    • অ স্থিতিশীল ডেটা সদস্য সহ কোনও বেস ক্লাস নেই, বা

    • সর্বাধিক উত্পন্ন ক্লাসে এবং অ স্থিতিশীল ডেটা সদস্য সহ সর্বাধিক এক বেস শ্রেণিতে কোনও অ স্থিতিশীল ডেটা সদস্য নেই

  2. (সি ++ ১৪ এবং তার পরে)

    • সমস্ত অ স্থিতিশীল ডেটা সদস্য এবং বিট-ফিল্ডগুলি একই শ্রেণিতে ঘোষিত হয়েছে (হয় সবগুলিই উত্পন্ন হয়েছে বা কোনও কোনও বেসে)

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

অধিকন্তু, এটি লক্ষণীয় যে পুরানো রিকার্সিভ-স্টাইলের টিপল সাধারণত ডেটা সদস্যদের বিপরীত ক্রমে রেখে দেয়।

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


1

পারফরম্যান্সের পার্থক্য থাকা উচিত নয় (এমনকি একটি তুচ্ছও)। কমপক্ষে স্বাভাবিক ক্ষেত্রে, তারা একই মেমরি বিন্যাসে ফল দেবে। তবুও, তাদের মধ্যে castালাই সম্ভবত কাজ করার প্রয়োজন নেই (যদিও আমি অনুমান করি যে এটির পক্ষে খুব সুন্দর সুযোগ আছে)।


4
আসলে আমি মনে করি একটি ছোট পার্থক্য থাকতে পারে। একজন structযখন আমি মনে করি এটি একটি প্রতিটি subobject জন্য অন্তত 1 বাইট বরাদ্দ আবশ্যক tupleখালি বস্তু আউট নিখুঁত পার পেয়ে যাবে। এছাড়াও, প্যাকিং এবং প্রান্তিককরণ সম্পর্কিত, এটি হতে পারে যে টিপলগুলির আরও অবকাশ থাকে।
ম্যাথিউ এম।

1

আমার অভিজ্ঞতা হ'ল সময়ের সাথে সাথে কার্যকারিতা প্রকারগুলিতে (পিওডি স্ট্রাক্ট) কমতে শুরু করে যা খাঁটি ডেটা ধারক হিসাবে ব্যবহৃত হত। নির্দিষ্ট পরিবর্তনগুলির মতো বিষয়গুলির জন্য যা তথ্যের অভ্যন্তরীণ জ্ঞানের প্রয়োজন হয় না, আক্রমণকারীগুলি বজায় রাখা ইত্যাদি should

এটা একটা ভাল জিনিস; এটি অবজেক্ট ওরিয়েন্টেশনের ভিত্তি। ক্লাস সহ সি উদ্ভাবন করার কারণেই এটি। টিপলসের মতো খাঁটি ডেটা সংগ্রহগুলি যেমন লজিক্যাল এক্সটেনশনের জন্য উন্মুক্ত নয়; স্ট্রাক্ট হয়। এজন্য আমি প্রায় সবসময় স্ট্রাক্ট বেছে নিই।

সম্পর্কিত যে সমস্ত "ওপেন ডেটা অবজেক্টস" এর মতো, টিপলসগুলি তথ্য গোপনের দৃষ্টান্ত লঙ্ঘন করে। টিউপল পাইকারকে বাইরে ফেলে ছাড়াই আপনি পরে এটি পরিবর্তন করতে পারবেন না । কাঠামোর সাহায্যে আপনি অ্যাক্সেস ফাংশনগুলির দিকে ধীরে ধীরে অগ্রসর হতে পারেন।

আর একটি সমস্যা হ'ল টাইপ সুরক্ষা এবং স্ব-ডকুমেন্টিং কোড। যদি আপনার ফাংশন কোনও প্রকারের অবজেক্ট পায় inbound_telegramবা location_3Dএটি পরিষ্কার; যদি এটি গ্রহণ করে unsigned char *বা tuple<double, double, double>এটি না হয়: টেলিগ্রামটি বহির্মুখী হতে পারে, এবং টিপলটি কোনও জায়গার পরিবর্তে অনুবাদ হতে পারে, বা দীর্ঘ উইকএন্ডের সর্বনিম্ন তাপমাত্রার পাঠ্য হতে পারে। হ্যাঁ, আপনি অভিপ্রায়গুলি স্পষ্ট করতে টাইপিডেফ করতে পারেন তবে এটি আপনাকে তাপমাত্রা পেরিয়ে যাওয়া থেকে বাধা দেয় না।

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

অবশ্যই একটি কার্যকর কৌশল হ'ল কোনও শ্রেণীর মোড়কের জন্য অন্তর্নিহিত ডেটা সরবরাহকারী হিসাবে খাঁটি ডেটা হোল্ডার ব্যবহার করা হবে যা সেই ডেটার উপর অপারেশন সরবরাহ করে।


1

গতি বা বিন্যাস সম্পর্কে চিন্তা করবেন না, এটি ন্যানো-অপটিমাইজেশন এবং সংকলকটির উপর নির্ভর করে এবং আপনার সিদ্ধান্তকে প্রভাবিত করার মতো যথেষ্ট পার্থক্য কখনও নেই।

পুরোপুরি গঠনের জন্য আপনি অর্থপূর্ণভাবে একত্রে থাকা বিষয়গুলির জন্য একটি কাঠামো ব্যবহার করেন।

কাকতালীয়ভাবে একসাথে থাকা জিনিসগুলির জন্য আপনি একটি টুপল ব্যবহার করেন। আপনি আপনার কোডটিতে স্বতঃস্ফূর্তভাবে একটি টুপল ব্যবহার করতে পারেন।


1

অন্যান্য উত্তরের দ্বারা বিচার করা, পারফরম্যান্স বিবেচনাগুলি সর্বনিম্ন ন্যূনতম।

সুতরাং এটি ব্যবহারিকতা, পঠনযোগ্যতা এবং রক্ষণাবেক্ষণের সত্যিকার অর্থে নেমে আসা উচিত। এবং structসাধারণত আরও ভাল কারণ এটি এমন ধরণের তৈরি করে যা পড়া এবং বোঝা সহজ।

কখনও কখনও, একটি std::tuple(বা এমনকি std::pair) একটি অত্যন্ত জেনারিক উপায়ে কোড মোকাবেলা করার প্রয়োজন হতে পারে। উদাহরণস্বরূপ, কিছু variadic প্যারামিটার প্যাকগুলি এর সাথে সম্পর্কিত অপারেশন ভালো কিছু ছাড়া সম্ভব নয় std::tuple। কোডটি std::tieকখন std::tupleউন্নত করতে পারে তার এক দুর্দান্ত উদাহরণ (সি ++ 20 এর পূর্বে)।

তবে আপনি যে কোনও জায়গায় ব্যবহার করতে পারেন struct, সম্ভবত আপনার ব্যবহার করা উচিতstruct । এটি আপনার ধরণের উপাদানগুলিতে অর্থপূর্ণ অর্থ প্রদান করবে। প্রকারটি বোঝার এবং ব্যবহারে এটি অমূল্য। পরিবর্তে, এটি নির্বোধ ভুল এড়াতে সাহায্য করতে পারে:

// hard to get wrong; easy to understand
cat.arms = 0;
cat.legs = 4;

// easy to get wrong; hard to understand
std::get<0>(cat) = 0;
std::get<1>(cat) = 4;

0

আমি জানি এটি একটি পুরানো থিম, তবে আমি এখন আমার প্রকল্পের অংশ সম্পর্কে সিদ্ধান্ত নিতে চলেছি: আমাকে কি টিউপল-ওয়ে বা কাঠামো পথে যেতে হবে? এই থ্রেডটি পড়ার পরে আমার কিছু ধারণা আছে।

  1. Whe Whees এবং পারফরম্যান্স পরীক্ষা সম্পর্কে: দয়া করে নোট করুন যে আপনি সাধারণত স্ট্রাইকগুলির জন্য মেমকি, মেমসেট এবং অনুরূপ কৌশল ব্যবহার করতে পারেন। এটি টিউপলসের চেয়ে পারফরম্যান্সকে আরও ভাল করে তুলবে।

  2. আমি টিপলসে কিছু সুবিধা দেখতে পাচ্ছি:

    • আপনি ফাংশন বা পদ্ধতি থেকে ভেরিয়েবলের সংগ্রহ ফিরিয়ে নিতে এবং আপনার ব্যবহারের ধরণের সংখ্যা হ্রাস করতে টিপলগুলি ব্যবহার করতে পারেন।
    • টিপল <, ==,> অপারেটরদের পূর্বনির্ধারিত হয়েছে এর উপর ভিত্তি করে আপনি মানচিত্র বা হ্যাশ_ম্যাপে কী হিসাবে টুপল ব্যবহার করতে পারেন যা আপনাকে এই অপারেটরগুলি প্রয়োগ করতে হবে এমন কাঠামোর চেয়ে অনেক বেশি কার্যকর effective

আমি ওয়েবটি অনুসন্ধান করেছি এবং শেষ পর্যন্ত এই পৃষ্ঠায় পৌঁছেছি: https://arne-mertz.de/2017/03/smelly-pair-tuple/

সাধারণত আমি উপর থেকে একটি চূড়ান্ত উপসংহার সাথে একমত।


4
এটি আপনি কী নিয়ে কাজ করছেন এবং সেই নির্দিষ্ট প্রশ্নের উত্তর নয়, এমনটি আরও শোনাচ্ছে বা?
ডিয়েটার মীমকেন

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