2012-07-10 17 views
12

मैं एक कक्षा को डिजाइन कर रहा हूं जिसमें std::vector<int> एक आवृत्ति चर के रूप में है। मैं std::vector का उपयोग कर रहा हूं क्योंकि मुझे रनटाइम पर अपना आकार सेट करने की आवश्यकता है। यहाँ मेरी कोड के प्रासंगिक अंश इस प्रकार हैं:कक्षा निर्माणकर्ता में सेटअप std :: वेक्टर

my_class.h: 

#include <vector> 
using std::vector; 
class MyClass { 
    int size; 
    vector<int> vec; 
} 

my_class.cc: 

#include "my_class.h" 
using std::vector 
MyClass::MyClass(int m_size) : size(m_size) { 
    vec = new vector<int>(size,0); 
} 

जब मैं मैं इन त्रुटि संदेश प्राप्त संकलन करने का प्रयास:,

g++ -c -Wall my_class.cc -o my_class.o 

my_class.cc: In constructor ‘MyClass::MyClass(int): 

    my_class.cc:4 error: no match for ‘operator=’ in ‘((MyClass*)this)->My_Class::vec = ((*(const allocator_type*)(& std::allocator<int>())), (operator new(24u), (<statement>, ((std::vector<int>*)<anonymous>))))’ 

make: *** [my_class.o] Error 1 

लेकिन जब मैं करने के लिए हमलावर लाइन बदलने के लिए:

vector<int> temp(size,0); 
vec = temp; 

अब यह एक झुकाव के बिना संकलित करता है और मुझे वांछित व्यवहार मिलता है और

के रूप में मेरे वेक्टर तक पहुंच सकता है

यह कामकाज ठीक है, लेकिन मैं समझना चाहता हूं कि यह क्यों काम करता है और पहली विधि विफल हो जाती है। अग्रिम में धन्यवाद।

+2

'नई vector' एक सूचक एक मान देता है नहीं, आप अपने सदस्य चर निर्दिष्ट करने के लिए सक्षम होने के लिए के लिए' vec' – Chethan

+2

मेरा अनुमान है आप जावा से आ रहा है या सी # और यदि हां, तो मेरी सलाह है गंभीर पहले एक अच्छी, प्रारंभिक सी ++ पुस्तक प्राप्त करने के लिए। –

+0

और प्रतिलिपि + पेस्ट विधि के माध्यम से हमेशा वास्तविक कोड पोस्ट करें। आपके द्वारा पोस्ट किया गया कोड अधूरा –

उत्तर

18

बस कार्य करें:

MyClass::MyClass(int m_size) : size(m_size), vec(m_size, 0) 

आप पहले से ही प्रारंभकर्ता सूची के बारे में पता करने के लिए लगता है, क्यों वेक्टर वहाँ सीधे प्रारंभ नहीं? क्योंकि new एक सूचक वापस आती है और अपने मामले vec में एक वस्तु है

vec = new vector<int>(size,0); 

गैर कानूनी है।

आपका दूसरा विकल्प: कोई लाभ के लिए अतिरिक्त काम

vector<int> temp(size,0); 
vec = temp; 

हालांकि यह संकलित करता है। जब तक आप असाइनमेंट तक पहुंचते हैं, तब तक दो वैक्टर पहले से ही निर्माण और त्याग दिए जाएंगे।

#include <vector> 

class MyClass { 
public: 
    MyClass(int m_size); 

    // ... more things... 
private: 
    int size; 
    vector<int> vec; 
} 

आप एक नया सदिश ऑब्जेक्ट के लिए सूचक बताए जाते हैं, जैसे कि इस सदिश वस्तु आरंभ नहीं किया गया था:

+1

आईआईआरसी इससे प्रारंभिक क्रम के कारण जीसीसी के साथ चेतावनियां पैदा होंगी - आपको कक्षा में सदस्य चर के समान प्रारंभिक सूची में प्रारंभिकरणों को आदेश देना चाहिए। – Fiktik

+0

टिप्पणी के लिए धन्यवाद, इसके आधार पर मैंने vec = * (नया वेक्टर (szie, 0) करने का प्रयास किया); और यह भी काम किया, लेकिन मैं प्रारंभकर्ता सूची का उपयोग करेंगे धन्यवाद! – fenkerbb

+0

@ user1269950 आपने जो किया वह गलत है - यह एक स्मृति रिसाव बनाता है। 'नया' ढेर पर एक स्मृति आवंटित करता है, वहां एक वस्तु बनाता है और इसमें एक सूचक देता है। आपने जो किया वह उस वस्तु की सामग्री को आपके सदस्य ऑब्जेक्ट को असाइन किया गया था और फिर मूल के बारे में भूल गया था - लेकिन यह अभी भी हमेशा के लिए आवंटित रहता है। जब आप 'नया' कहते हैं तो आपको हमेशा उस पते को सहेजना होगा जो उसे लौटाता है (एक पॉइंटर में) और अंत में उस पॉइंटर पर 'हटाएं' को कॉल करें! – Fiktik

8

वेक्टर के उपयोग अपनी कक्षा में कानूनी है, समस्या यह है कि आप इसे प्रारंभ है।

vec = new vector<int>(size,0); 

आप वास्तव में इस काम करने के लिए चाहते हैं, तो आप अपने vec वस्तु घोषित करना चाहिए के रूप में:

vector<int> * vec; 

और भूल जाते हैं एक नाशक जोड़ने के लिए नहीं है:

MyClass::~MyClass { 
    delete vec; 
} 

क्यों जब आप new कण गिराते हैं तो यह काम करता है? चूंकि आप एक नई वस्तु vector बना रहे हैं, और आपकी कक्षा में ओवरराइटिंग (यह मूल को सही तरीके से समाप्त करने की गारंटी नहीं देता है)।

आपको वास्तव में ऐसा करने की आवश्यकता नहीं है। जब आप MyClass के निर्माता तक पहुंच गए हैं तो आपकी vector ऑब्जेक्ट पहले ही प्रारंभ हो चुकी है (इसका डिफ़ॉल्ट कन्स्ट्रक्टर कहा जाता है)।

MyClass::MyClass(int m_size): size(m_size) { 
    vec.reserve(size); 
} 

आप अपने वेक्टर size तत्वों, तो करना चाहते हैं:

MyClass::MyClass(int m_size): size(m_size), vec(m_size, 0) 
    {} 

अंत में, टिप्पणीकर्ताओं में से एक बताते हैं तो आप सिर्फ यह सुनिश्चित करें कि स्मृति size आइटम के लिए आरक्षित है होना चाहते हैं वेक्टर के निर्माण के बाद आकार की वास्तव में आवश्यकता नहीं होती है। तो तुम size सदस्य से छुटकारा पाने के कर सकते हैं:

class MyClass { 
public: 
    MyClass(int m_size): vec(m_size, 0) 
     {} 

    unsigned int getSize() const 
     { return vec.size(); } 

    // ... more things... 
private: 
    vector<int> vec; 
} 

आशा इस मदद करता है।

+1

@OP - 'वेक्टर' इसका आकार जानता है, इसलिए यदि सभी 'आकार' कर रहे हैं तो 'वेक्टर' में तत्वों की संख्या का ट्रैक रखना, तो सुझाव है कि आप 'आकार' से छुटकारा पाएं। –

+0

बहुत सच है, मैं आपकी टिप्पणी को शामिल करने के लिए अपने उत्तर को संशोधित कर दूंगा। – Baltasarq

1
#include <vector> 
#include <iostream> 
#include <string> 
#include <typeinfo> 

using std::cout; 
using std::endl; 
using std::string; 
using std::vector; 
using std::to_string; 

class Parse 
{ 
private: 
    string   m_str; 
    vector<string> m_vec; 
public: 
    // Constructor with all defaults (1 of 4 constructors) 
    Parse(){ 
     cout << "\ncreating class with all default values\n"; 
     m_str = ""; 
     m_vec.push_back("");  
    } 

    // Constructor with all cases used 
    Parse (string   &tmp_str, 
      vector<string> tmp_vec): 

      m_str   (tmp_str), 
      m_vec   (tmp_vec) 
    { 
     cout << "Your vector contains " + to_string(m_str.size()) + " arguments\n"; 
    } 

    // Constructor with other contents given but not vector 
    Parse (string   &tmp_str): 
      m_str   (tmp_str) 
    { 
     m_vec.push_back(""); 
    } 
    // Constructor with only Vector given but not other contents 
    Parse (vector<string> tmp_vec): 
      m_vec   (tmp_vec) 
    { 
     m_str = ""; 
    } 

    string get_str_var(){return m_str;} 

    void classed_print_vector_strings() 
    { 
     for (string i : m_vec){ cout << i << " \n";} 
    } 

}; 



// rm ./class_vector; g++ class_vector.cpp -o class_vector -std=c++17; ./class_vector arg1 arg2 arg3 

int main(int argc, char *argv[]) 
{ 
    // turn **argv to a vector 
    vector<string> args(argv, argv + argc); 
    // iterate from argv through argv+argc 

    // initialize with default arguments. 
    Parse tracker1; 
    // initalize with all used arguments 
    Parse tracker2(args[0], args); 
    // initalize with only the vector 
    Parse tracker3(args); 
    // initalzie without the vector, but with another arg 
    Parse tracker4(args[0]); 

    cout << "\nTracker 1 ---------------------\n"; 
    tracker1.classed_print_vector_strings(); 
    cout << "\nTracker 2 ---------------------\n"; 
    tracker2.classed_print_vector_strings(); 
    cout << "\nTracker 3 ---------------------\n"; 
    tracker3.classed_print_vector_strings(); 
    cout << "\nTracker 4 ---------------------\n"; 
    tracker4.classed_print_vector_strings(); 


    return 0; 
} 

// rm ./class_vector; g++ class_vector.cpp -o class_vector -std=c++17; ./class_vector arg1 arg2 arg3 

// This will show you how to create a class that will give 
// you the option to initilize the class with or without 
// the vector with other arguments present and/or not present. 

// My Background. . . 
// github.com/Radicalware 
// Radicalware.net 
// https://www.youtube.com/channel/UCivwmYxoOdDT3GmDnD0CfQA/playlists 
संबंधित मुद्दे