2015-08-25 8 views
5

मैं अपने पहले जंग कार्यक्रम पर काम कर रहा हूं, और जंग के स्वामित्व अर्थशास्त्र से दूर भाग गया हूं। मैंने struct घोषित किया है जो एक स्क्लाइट डेटाबेस कनेक्शन को समाहित करेगा, इसलिए यह SqliteConnection सदस्य बनाए रखता है। प्रदर्शन कारणों से मैं SqliteStatement प्रकार द्वारा प्रतिनिधित्व किए गए एक तैयार कथन को भी रखना चाहता हूं। यहाँ मेरी कोड का एक सरलीकृत संस्करण है:जंग में एक ही संरचना में एक स्क्लाइटकनेक्शन और स्क्लाइटस्टेटमेंट ऑब्जेक्ट्स को कैसे स्टोर करें?

use rusqlite::{SqliteConnection, SqliteTransaction, SqliteStatement}; 
use rusqlite; 

pub struct Foo<'a> { 
    conn: SqliteConnection, 
    statement: SqliteStatement<'a> 
} 

impl<'a> Foo<'a> { 
    pub fn new() -> Foo<'a> { 
     let mut conn = SqliteConnection::open(&":memory:").unwrap(); 
     let statement = conn.prepare("INSERT INTO Foo(name, hash) VALUES($1, $2)").unwrap(); 
     Foo { conn: conn, statement: statement } 
    } 
} 

मैं Foo के एक सदस्य में संग्रहीत करके कॉल प्राप्त करने वाला को conn चर का स्थानान्तरण करने का कोशिश कर रहा हूँ, लेकिन यह विफल रहता है जब मैं इस कोड को संकलित करने का प्रयास:

error: `conn` does not live long enough 
note: reference must be valid for the lifetime 'a as defined on the block at 10:25... 
... 
note: ...but borrowed value is only valid for the block suffix following statement 0 at 11:62 

किसी कारण से, rusqlite टोकरा में SqliteConnection प्रकार एक जीवन भर पैरामीटर नहीं ले करता है, तो मैं स्पष्ट रूप से SqliteStatement उदाहरण की है कि अपने जीवनकाल टाई करने में असमर्थ हूँ।

मुझे क्या याद आ रही है? इस प्रकार का encapsulation एक बहुत ही आम पैटर्न है, मुझे यकीन है कि मैं कुछ याद कर रहा हूँ। अगर हम SqliteResult उपेक्षा (जो सिर्फ मतलब है कि यह समारोह असफल हो सकता है)

fn prepare<'a>(&'a self, sql: &str) -> SqliteResult<SqliteStatement<'a>> 

, इसका मतलब है "वापस एक SqliteStatementSqliteConnection कि prepare से अधिक समय नहीं रह सकते हैं कि कहा जाता था:

+0

यह वही समस्या है जैसे http://stackoverflow.com/q/20698384/155423 या http://stackoverflow.com/q/30538387/155423 या वास्तव में सवाल पूछने वाले कई प्रश्नों में से कोई भी "कैसे करें मेरे पास 'foo' का संदर्भ है और फिर 'foo' को स्थानांतरित करें? "। कल से यह प्रश्न था [http://stackoverflow.com/q/32194269/155423) साथ ही साथ। संक्षिप्त संस्करण यह है कि एक बार जब आप किसी आइटम में संदर्भ डालते हैं, तो आप उस आइटम को स्थानांतरित नहीं कर सकते हैं क्योंकि यह संदर्भ को अमान्य कर देगा। – Shepmaster

+0

टिप्पणी के लिए धन्यवाद। शायद मैं नामकरण को गलत समझ रहा हूं, लेकिन मेरे उदाहरण में मुझे नहीं लगता कि मैं संदर्भों का उपयोग कर रहा हूं। मैं 'नए' फ़ंक्शन के दायरे से 'FU' संरचना के दायरे से 'स्क्लाइट कनेक्शन' के स्वामित्व को स्थानांतरित करना चाहता हूं, जिसका स्वयं ही 'नए' फ़ंक्शन के कॉलर के स्वामित्व में होना है। – anelson

+0

मैं आपके शीर्षक को कुछ और विशिष्ट रूप में बदलने की अनुशंसा करता हूं, जैसे "मेरे पास एक ही संरचना में 'स्क्लाइटस्टेटमेंट' और 'स्क्लाइटकनेक्शन' कैसे है"। जैसा कि अब है, आपका शीर्षक पर्याप्त रूप से केंद्रित नहीं है क्योंकि एक संरचना में स्वामित्व स्थानांतरित करना आसान है, लेकिन आपकी समस्या क्या नहीं है। – Shepmaster

उत्तर

4

के SqliteConnection::prepare पर नजर डालते हैं पर"। यह SqliteStatement के कारण SqliteConnection का संदर्भ है।

हालांकि, यदि आपके पास किसी आइटम का संदर्भ है, तो आप अब आइटम को स्थानांतरित नहीं कर सकते क्योंकि संदर्भ अमान्य हो जाएगा। उस अमान्य संदर्भ का उपयोग करने से स्मृति असुरक्षित हो जाएगी, इसलिए इसे रोका जा सकता है।

असल में, आपको अपने कोड में इन वस्तुओं के जीवनकाल और स्वामित्व को दर्पण करने की आवश्यकता है, और इसलिए आप उसी संरचना में SqliteConnection और SqliteStatement को बंडल नहीं कर सकते हैं। इसके बजाय, कोई दूसरे का संदर्भ दे सकता है।

+0

आह! यही वह था जो मैं याद कर रहा था। धन्यवाद। – anelson

+1

एक एसक्यूएल कनेक्शन + 2 तैयार कथन वास्तव में वास्तविक कोड की तरह दिखेंगे? –

संबंधित मुद्दे