मैं मानक पुस्तकालय के स्मार्ट पॉइंटर्स, unique_ptr
और shared_ptr
के साथ पढ़ रहा हूं और प्रयोग कर रहा हूं और हालांकि वे बहुत से मामलों के लिए स्पष्ट रूप से महान प्रतिस्थापन हैं जहां कच्चे पॉइंटर्स को खतरनाक समझा जा सकता है, मैं डेटा संरचनाओं को लागू करते समय उनके उपयोग से अनिश्चित हूं।डेटा संरचनाओं को लागू करते समय स्मार्ट या कच्चे पॉइंटर्स?
प्रयोग करने के लिए, मैंने एक हैश मानचित्र का एक उदाहरण लिखा है जो shared_ptr
का उपयोग करता है - जो मेयर के प्रभावी आधुनिक सी ++ के अनुसार लगभग unique_ptr
के आकार को दोगुना कर देता है। इस कारण से मैं unique_ptr का उपयोग करना चाहता हूं लेकिन मैं फंक्शन, अपडेटिंग और कॉपी करने में जो कर रहा हूं उसके कारण मैं स्टंप हूं।
क्या किसी को इस समस्या के लिए कोई सुझाव है? कच्चे पॉइंटर्स का उपयोग कर डेटा संरचनाओं को लिखा जाना चाहिए?
#pragma once
#include "core.h"
const int TABLE_SIZE = 256;
template<typename K>
class HashKey {
public:
unsigned long operator()(const K& p_key) const {
return (p_key) % TABLE_SIZE;
}
};
template<typename K, typename T>
class HashNode {
public:
K m_key;
T m_value;
std::shared_ptr<HashNode> next = nullptr;
};
template<typename K, typename T, typename F = HashKey<K>>
class HashMap {
public:
std::array< std::shared_ptr< HashNode<K, T> >, 128 > m_table;
F m_hash_function;
int m_elem_count{ 0 };
void Add(K p_key, T p_value);
};
template<typename K, typename T, typename F = HashKey<K>>
void HashMap<K, T, F>::Add(K p_key, T p_value)
{
unsigned long key = m_hash_function(p_key);
std::shared_ptr<HashNode<K, T>> new_node = std::make_shared<HashNode<K, T>>();
new_node->m_key = p_key;
new_node->m_value = p_value;
if (m_table[key] == nullptr) {
/* only item in the bucket */
m_table[key] = std::move(new_node);
m_elem_count++;
}
else {
/* check if item exists so it is replaced */
std::shared_ptr< HashNode<K, T> > current = m_table[key];
std::shared_ptr< HashNode<K, T> > previous = m_table[key];
while (current != nullptr && p_key != current->m_key) {
previous = current;
current = current->next;
}
if (current == nullptr) {
previous->next = new_node;
//current = new_node;
m_elem_count++;
}
else {
current->m_value = p_value;
}
}
}
void TestHashMap() {
HashMap<int, std::string> hash_map;
hash_map.Add(1, "one");
hash_map.Add(2, "does");
hash_map.Add(3, "not");
hash_map.Add(50, "simply");
hash_map.Add(11, "waltz");
hash_map.Add(11, "into");
hash_map.Add(191, "mordor");
std::cout << hash_map.m_elem_count << std::endl;
}
आम तौर पर, आपको ऑटो-डिलीटिंग पॉइंटर्स के बजाय * स्वामित्व * के संदर्भ में नए स्मार्ट पॉइंटर्स के बारे में सोचना चाहिए।क्या "संसाधन" में एक साथ कई एक साथ मालिक ('std :: shared_ptr') या केवल एक ही ऑनवर हो सकता है (' std :: unique_ptr')। –
मुझे यकीन नहीं है कि आप इस मामले के लिए यहां पॉइंटर्स की आवश्यकता क्यों महसूस करते हैं - या 'std :: array'। आप 'std :: vector <हैश नोड>' के संदर्भ में हैश मानचित्र को क्यों लागू नहीं करेंगे? आम तौर पर, प्रश्न मुझे थोड़ा सा पहेली करता है: आपको जो करना चाहिए वह अधिकांश डेटा संरचनाओं (और उनके लिए एल्गोरिदम) लिखना है। नतीजतन, आप निश्चित रूप से * डेटा संरचनाओं के लिए स्मार्ट प्वाइंटर्स, गूंगा पॉइंटर्स का उपयोग नहीं करेंगे - फिर आप स्मार्ट पॉइंटर्स का और क्या उपयोग करेंगे? और कुछ नहीं है। –
एक पेड़ डेटा संरचना में घुमाव जैसे कोड लिखते समय, मैं माइक्रो ऑप्टिमाइज़ करता हूं, जिसमें आमतौर पर पॉइंटर्स का उपयोग वैचारिक स्वामित्व छोड़ने के बाद कुछ निर्देशों का उपयोग करना शामिल होता है। जब तक मैं कच्चे पॉइंटर्स का उपयोग कर रहा हूं और मैं कोड के स्वामित्व अर्थशास्त्र को समझता हूं, तो मैं स्वामित्व नियमों को झुका सकता हूं जहां यह सुरक्षित और कुशल है। स्मार्ट पॉइंटर के साथ, ऑप्टिमाइज़र जेनरेट कोड को कभी भी उतना कुशल नहीं बना सकता जितना कि मैंने कच्चे पॉइंटर्स के साथ लिखा होगा। एक कम कुशल प्रोग्रामर को लाभ के लिए कम अवसर मिलेगा और अधिक गलतियों का जोखिम होगा। – JSF