- 질문 게시판입니다.
Date | 24/04/17 15:48:38수정됨 |
Name | T.Robin |
Subject | Rust 프로그래밍: constructor 내부 closure에서 Self의 객체를 불러서 처리하기 |
Rust 도전 일주일차인 T.Robin입니다(아 응애에요). 대충 아래의 코드가 있습니다. struct S1 { element1: AAA, element2: BBB, } impl S1 { pub fn new()->Self { let result = Self { element1: Element1::new(), element2: Element2::new() } // 뭔가 이것저것...... result.element1.do_something( { let element1_weak_reference = result.element1.get_weak_reference().unwrap(); move || { // 여기가 문제 result.element2.do_something_else( element1_weak_reference.do_something() ); } }); // 완료 result } } 아마 눈치채셨겠지만, 이 코드는 빌드되지 않습니다. [//여기가 문제] 부분에서 result.element2가 closure 안쪽으로 이동해버려서, 마지막 "[//완료]" 부분에서는 result.element2가 아직 변수를 빌려준 상태로 남아있게 되어서 컴파일러가 투덜댑니다(요컨데, closure가 본문보다 더 오래 살아남을 수 있다....... 뭐 이런 내용입니다). 아예 unsafe 선언하고 C++ 스타일 raw pointer로 막무가내로 밀어부쳐 보기도 했습니다만 프로그램이 터지는걸 보면 이것도 답은 아닌 것 같습니다. 이 경우, 어떻게 처리해야 될까요? 0
이 게시판에 등록된 T.Robin님의 최근 게시물
|
전 아니고 chatGPT 4.0가 이렇게 추천하는군요
여기서 발생하는 문제는 `result`라는 변수의 소유권이 `do_something` 클로저 내부로 이동하려고 하기 때문입니다. 러스트에서는 하나의 변수에 대한 소유권을 다른 스코프로 이동할 수 없으며, 이런 이동이 발생하려고 하면 컴파일 에러가 발생합니다. 여기서는 `result`가 이 함수의 마지막에서 반환되어야 하기 때문에 클로저 내부에서 이 변수를 직접 사용하는 것은 불가능합니다.
문제를 해결하기 위해 몇 가지 접근 방식을 사용할 수 있습니다:
1. **클... 더 보기
여기서 발생하는 문제는 `result`라는 변수의 소유권이 `do_something` 클로저 내부로 이동하려고 하기 때문입니다. 러스트에서는 하나의 변수에 대한 소유권을 다른 스코프로 이동할 수 없으며, 이런 이동이 발생하려고 하면 컴파일 에러가 발생합니다. 여기서는 `result`가 이 함수의 마지막에서 반환되어야 하기 때문에 클로저 내부에서 이 변수를 직접 사용하는 것은 불가능합니다.
문제를 해결하기 위해 몇 가지 접근 방식을 사용할 수 있습니다:
1. **클... 더 보기
전 아니고 chatGPT 4.0가 이렇게 추천하는군요
여기서 발생하는 문제는 `result`라는 변수의 소유권이 `do_something` 클로저 내부로 이동하려고 하기 때문입니다. 러스트에서는 하나의 변수에 대한 소유권을 다른 스코프로 이동할 수 없으며, 이런 이동이 발생하려고 하면 컴파일 에러가 발생합니다. 여기서는 `result`가 이 함수의 마지막에서 반환되어야 하기 때문에 클로저 내부에서 이 변수를 직접 사용하는 것은 불가능합니다.
문제를 해결하기 위해 몇 가지 접근 방식을 사용할 수 있습니다:
1. **클로저 내부에서 `result`의 특정 필드에만 접근하고, 전체 구조체를 클로저 안으로 이동하지 않도록 합니다.** 이를 위해 `element2`를 별도의 변수로 분리하고 이를 클로저로 이동할 수 있습니다. 그러나 이 경우 `element1`과 `element2` 간의 상호작용을 클로저 안에서 처리하기 어려울 수 있습니다.
2. **Arc와 Mutex 또는 RwLock을 사용하여 `element1`과 `element2`를 공유합니다.** 이 방법은 멀티 스레드 환경에서도 안전하게 요소들을 공유할 수 있게 합니다. 클로저에서는 `Arc<Mutex<_>>` 또는 `Arc<RwLock<_>>`를 통해 각 요소에 접근할 수 있습니다.
다음은 `Arc`와 `Mutex`를 사용한 예시 코드입니다:
```rust
use std::sync::~{Arc, Mutex};
struct Element1 ~{
// element1의 필드들
}
impl Element1 ~{
fn new() -> Self ~{
Self ~{ /* 초기화 */ }
}
fn get_weak_reference(&self) -> Option<Arc<Mutex<Self>>> ~{
Some(Arc::new(Mutex::new(Self ~{ /* 초기화 */ })))
}
fn do_something(&self) ~{
// element1의 동작
}
}
struct Element2 ~{
// element2의 필드들
}
impl Element2 ~{
fn new() -> Self ~{
Self ~{ /* 초기화 */ }
}
fn do_something_else(&self, _: ()) ~{
// element2의 동작
}
}
struct S1 ~{
element1: Arc<Mutex<Element1>>,
element2: Arc<Mutex<Element2>>,
}
impl S1 ~{
pub fn new() -> Self ~{
let element1 = Arc::new(Mutex::new(Element1::new()));
let element2 = Arc::new(Mutex::new(Element2::new()));
let element1_clone = Arc::clone(&element1);
let element2_clone = Arc::clone(&element2);
let result = Self ~{
element1,
element2,
};
// Mutex로 감싸진 element1의 약한 참조를 얻음
if let Some(element1_weak_reference) = element1_clone.lock().unwrap().get_weak_reference() ~{
let element2_weak = element2_clone;
element1_clone.lock().unwrap().do_something(~{
move || ~{
// 여기서 element2의 Mutex를 잠그고 함수를 호출
element2_weak.lock().unwrap().do_something_else(element1_weak_reference.lock().unwrap().do_something());
}
});
}
result
}
}
fn main() ~{
let s = S1::new();
}
```
위 코드에서는 `Element1`과 `Element2`를 `Arc<Mutex<_>>`로 감싸서 클로저 안에서 안전하게 사용할 수 있도록 합니다. 클로저는 `element2`의 `Mutex`를 잠근 후 `do_something_else`를 호출합니다. 이렇게 하면 소유권 문제를 회피하면서도 동시성을 유지할 수 있습니다.
여기서 발생하는 문제는 `result`라는 변수의 소유권이 `do_something` 클로저 내부로 이동하려고 하기 때문입니다. 러스트에서는 하나의 변수에 대한 소유권을 다른 스코프로 이동할 수 없으며, 이런 이동이 발생하려고 하면 컴파일 에러가 발생합니다. 여기서는 `result`가 이 함수의 마지막에서 반환되어야 하기 때문에 클로저 내부에서 이 변수를 직접 사용하는 것은 불가능합니다.
문제를 해결하기 위해 몇 가지 접근 방식을 사용할 수 있습니다:
1. **클로저 내부에서 `result`의 특정 필드에만 접근하고, 전체 구조체를 클로저 안으로 이동하지 않도록 합니다.** 이를 위해 `element2`를 별도의 변수로 분리하고 이를 클로저로 이동할 수 있습니다. 그러나 이 경우 `element1`과 `element2` 간의 상호작용을 클로저 안에서 처리하기 어려울 수 있습니다.
2. **Arc와 Mutex 또는 RwLock을 사용하여 `element1`과 `element2`를 공유합니다.** 이 방법은 멀티 스레드 환경에서도 안전하게 요소들을 공유할 수 있게 합니다. 클로저에서는 `Arc<Mutex<_>>` 또는 `Arc<RwLock<_>>`를 통해 각 요소에 접근할 수 있습니다.
다음은 `Arc`와 `Mutex`를 사용한 예시 코드입니다:
```rust
use std::sync::~{Arc, Mutex};
struct Element1 ~{
// element1의 필드들
}
impl Element1 ~{
fn new() -> Self ~{
Self ~{ /* 초기화 */ }
}
fn get_weak_reference(&self) -> Option<Arc<Mutex<Self>>> ~{
Some(Arc::new(Mutex::new(Self ~{ /* 초기화 */ })))
}
fn do_something(&self) ~{
// element1의 동작
}
}
struct Element2 ~{
// element2의 필드들
}
impl Element2 ~{
fn new() -> Self ~{
Self ~{ /* 초기화 */ }
}
fn do_something_else(&self, _: ()) ~{
// element2의 동작
}
}
struct S1 ~{
element1: Arc<Mutex<Element1>>,
element2: Arc<Mutex<Element2>>,
}
impl S1 ~{
pub fn new() -> Self ~{
let element1 = Arc::new(Mutex::new(Element1::new()));
let element2 = Arc::new(Mutex::new(Element2::new()));
let element1_clone = Arc::clone(&element1);
let element2_clone = Arc::clone(&element2);
let result = Self ~{
element1,
element2,
};
// Mutex로 감싸진 element1의 약한 참조를 얻음
if let Some(element1_weak_reference) = element1_clone.lock().unwrap().get_weak_reference() ~{
let element2_weak = element2_clone;
element1_clone.lock().unwrap().do_something(~{
move || ~{
// 여기서 element2의 Mutex를 잠그고 함수를 호출
element2_weak.lock().unwrap().do_something_else(element1_weak_reference.lock().unwrap().do_something());
}
});
}
result
}
}
fn main() ~{
let s = S1::new();
}
```
위 코드에서는 `Element1`과 `Element2`를 `Arc<Mutex<_>>`로 감싸서 클로저 안에서 안전하게 사용할 수 있도록 합니다. 클로저는 `element2`의 `Mutex`를 잠근 후 `do_something_else`를 호출합니다. 이렇게 하면 소유권 문제를 회피하면서도 동시성을 유지할 수 있습니다.
목록 |
|