मैं वर्तमान में एक sqlite3 लाइब्रेरी फ़ंक्शन को कॉल करने का प्रयास कर रहा हूं, और यह मुझसे इसे sqlite3** पास करने की अपेक्षा करता है।

यहाँ मेरा वर्तमान कोड है। मेरे पास एक काम करने वाला हिस्सा है, और एक हिस्सा जो मुझे एक त्रुटि देता है:

sqlite3 *sqlite = m_db.get();
if (sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &sqlite))
{

}

if (sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &(m_db.get()) ))
{

}

मेरा m_db फ़ील्ड इस तरह दिखता है:

std::unique_ptr<sqlite3> m_db = nullptr;

मैंने जो दो उदाहरण प्रदर्शित किए, उनमें से पहला बिल्कुल ठीक काम कर रहा है। हालाँकि, दूसरा मुझे यह त्रुटि देता है। ध्यान दें कि यह &(m_db.get()) भाग से आ रहा है:

“Address expression must be an lvalue or a function designator”

मैंने अंतराल और प्रतिद्वंद्विता के बारे में कुछ पढ़ा है, लेकिन मुझे यह पता नहीं लग रहा है कि यह वाक्यविन्यास क्यों संभव नहीं होगा। जहां तक ​​मुझे अब तक समझ में आया, समस्या यह है कि .get() ऑपरेशन का रिटर्न वैल्यू केवल एक अस्थायी अभिव्यक्ति परिणाम है, और इसलिए स्मृति में एक पहचान योग्य स्थान नहीं है जहां से मैं पता प्राप्त कर सकता हूं।

मुझे लगता है कि एक बयान में इसे हासिल करने का एक तरीका होना चाहिए।

क्या कोई मुझे समझा सकता है कि यह क्यों काम नहीं कर रहा है और मैं इसे कैसे ठीक कर सकता हूं?

c++
5
Sossenbinder 27 मई 2016, 11:09

4 जवाब

सबसे बढ़िया उत्तर

& ऑपरेटर का उपयोग केवल एक लैवल्यू (या पॉइंटर-टू-सदस्य बनाते समय एक योग्य आईडी के साथ) के साथ किया जा सकता है। व्यंजक m_db.get() एक प्रतिद्वंद्विता है क्योंकि यह मान के आधार पर एक सूचक देता है, संदर्भ से नहीं, इसलिए आप इसका पता नहीं ले सकते।

unique_ptr अंतर्निहित पॉइंटर को संदर्भ के रूप में एक्सेस करने के लिए कोई तरीका प्रदान नहीं करता है, आपको अपने पहले उदाहरण की तरह एक कॉपी को कहीं स्टोर करने की आवश्यकता होगी।

8
user657267 27 मई 2016, 11:15

एक स्मार्ट पॉइंटर एक पॉइंटर को स्टोर करता है और इसे पाने पर लौटाता है। आप यहां जो करना चाहते हैं वह इसके विपरीत है: आपको sqlite3_open से एक पॉइंटर मिलता है और आप इसे स्मार्ट पॉइंटर में स्टोर करना चाहते हैं। तो आप कुछ ऐसा करेंगे

sqlite3* db = nullptr;
sqlite3_open(..., &db);
m_db.reset(db);

चूंकि unique_ptr की मुख्य विशेषता इसके विनाशक में निहित सूचक को हटाना है, मुझे यकीन नहीं है कि इसे यहां उपयोग करने के लिए समझ में आता है या नहीं। जहां तक ​​मैं इसे समझता हूं, आपको लौटाए गए पॉइंटर पर sqlite3_close पर कॉल करना चाहिए, इसे डिलीट नहीं करना चाहिए।

3
Karsten Koop 27 मई 2016, 11:22

मुझे लगता है कि एक बयान में इसे हासिल करने का एक तरीका होना चाहिए।

मैं इसके बारे में निश्चित नहीं हूँ; अस्थायी मूल्यों के बारे में बात वास्तव में यह हो सकती है कि स्थायी प्राप्त करने के लिए एक बयान लेता है।

साथ ही, आप स्मार्ट पॉइंटर के शब्दार्थ के साथ खिलवाड़ कर रहे हैं, जो आपको नहीं करना चाहिए - .get का वास्तव में यहां उपयोग नहीं किया जाना चाहिए।

Sooooo, मैं क्या करूँगा यहाँ C++ स्कोपिंग पर निर्भर है, और इस तथ्य की परवाह नहीं करता कि मैं बाद में एक स्मार्ट पॉइंटर बनाने के लिए पहले "सामान्य" पॉइंटर घोषित करता हूँ।

your_class::initialize_db() {
    sqlite3 *sqlite;
    int retval = sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &sqlite);
    if(retval == SQLITE_OK) 
        m_db = std::unique_ptr<sqlite3>(sqlite);

}
1
Marcus Müller 27 मई 2016, 11:20

एक लैवल्यू मूल रूप से कुछ ऐसा होता है जो असाइनमेंट ऑपरेटर के बाईं ओर दिखाई दे सकता है। तो त्रुटि कहती है कि आप केवल उस चीज़ का पता पुनर्प्राप्त कर सकते हैं जिसे असाइन किया जा सकता है, या कोई फ़ंक्शन। यदि आपके पास अद्वितीय_ptr के अंदर sqlite3 * पॉइंटर तक सदस्य पहुंच होती, तो यह काम करता, लेकिन आप नहीं करते हैं, और अच्छे कारण के लिए।

इस मामले में, आपको स्मार्ट पॉइंटर का उपयोग नहीं करना चाहिए। यदि sqlite3_open को sqlite3** तर्क की आवश्यकता है, तो इसका अर्थ है कि फ़ंक्शन sqlite3* सूचक के लिए एक मान प्रदान करेगा। मूल रूप से यह एक out पैरामीटर फॉर्म C# या ऐसी अन्य भाषा है। यह एक फ़ंक्शन परिणाम के रूप में प्रदान करने के लिए स्पष्ट होता, लेकिन वह परिणाम कोड द्वारा हटा दिया गया था। यह सब ठीक है और अच्छा है, लेकिन स्मार्ट पॉइंटर इस मूल्य पर नियंत्रण रखना चाहता है। आप प्रारंभ में एक बार मान सेट करते हैं, लेकिन उसके बाद, स्मार्ट पॉइंटर इसका ख्याल रखता है। और इसे अपनी बाधाओं को बनाए रखने के लिए ऐसा करने की आवश्यकता है: स्वामित्व की विशिष्टता, डिलोकेशन जब पॉइंटर स्वयं ही दायरे से बाहर हो जाता है आदि। यदि आप मूल रूप से sqlite3 * पॉइंटर को अंदर जाकर ओवरराइट करते हैं, तो यह अब और नहीं हो सकता है, क्योंकि स्मार्ट पॉइंटर के पास वर्तमान में उपयोग की जा रही वस्तु को अधिलेखित करने और हटाने को रोकने का कोई तरीका नहीं है।

1
Horia Coman 27 मई 2016, 11:26