2011-01-26 5 views
7

가능합니까? 그렇다면 Qt에서 shared_ptr에 대한 const 참조 인 신호/슬롯을 어떻게 만들 수 있습니까? 나는이처럼 보이는 신호를 원하는 :신호/슬롯에서 boost :: shared_ptr을 사용하는 Qt

void signal(shared_ptr<SomeClass> const &)

내가 일정한 기준없이이 작업을 수행하는 방법을 알고, 즉 단순히 유형 shared_ptr<SomeClass>하지만 복사를 방지하고 싶습니다 효율성 * 이유입니다. 참조 유형에 대한 동일한 구문이 작동하지 않습니다 : 표준 API를

Q_DECLARE_METATYPE(shared_ptr<SomeClass> const &) 
qRegisterMetaType<shared_ptr<SomeClass> const&>(); 

많은 사람들이 그래서 그것을 근본적으로 가능하다 생각 난 그냥 구문을 알아낼 수 없습니다 QString const & 있습니다.


은 ** 성능에 대한 가장 큰 문제는 복사 시간이 아니라 객체로 뮤텍스 잠금/잠금 해제의 양이 모든 수신기에 복사됩니다 - 그 중 많이 있습니다. 여러 스레드가 객체를 사용함에 따라 눈에 띄는 속도 저하/병목 현상이 발생합니다. shared_ptr의 사실 않으면 그냥 신호에 const를 참조에 대한 일반적인 질문은 그러나 여전히이 비용도 사소한 원자 연산을 사용 * 지금까지 내가 단순히이 할 수있는 것을 발견했다

+0

shared_ptr을 const 참조로 전달하지 않으면 먼저 shared_ptr이있는 지점이 무효화됩니까? 문제의 객체에 const 참조/포인터를 전달하십시오. – messenger

+1

@messenger, const 참조는 함수 호출시 shared_ptr 복사를 피하기위한 최적화입니다. 이것은 매우 일반적인 패턴입니다. 값 (신호 또는 일반 함수)을 항상 전달하면 shared_ptr은 일반 포인터와 비교할 때 상당히 비쌉니다. 정상적인 포인터는 "방출"측의 객체 수명이 보장되지 않으므로 여기에서 사용할 수 없습니다. –

+0

@ edA-qa mort-ora-y : 부스트 shared_ptr이 뮤텍스를 사용합니까 ??? 왜 그 ??? 원자 증가/감소가 모두 필요하지 않습니까? – mmmmmmmm

답변

7

:.

Q_DECLARE_METATYPE(shared_ptr<SomeClass>) 
qRegisterMetaType<shared_ptr<SomeClass> >(); 
qRegisterMetaType<shared_ptr<SomeClass> >("std::shared_ptr<SomeClass>const&"); 

저는 이것이 진정으로 올바르게 작동하는지 이제 확인하려고합니다. 여기에있는 문서는 실제로 어떤 일이 일어나는지 명확하지 않습니다. 신호/슬롯의 const 참조 유형은 보통 shared_ptr<SomeClass>으로 마샬링됩니다. 여기서는 완전히 괜찮습니다. 이것이 일하기로되어있는 일종의 보장을하는 것이 좋을 것입니다.

단순한 shared_ptr<SomeClass> 버전이 모두 필요하다는 느낌이 들며 신호를 방해하는 것은 boost 네임 스페이스입니다. 두 번째 버전은 더 쉽게 사용할 수 있도록 전역 네임 스페이스에 신호를 등록하는 것으로 나타납니다. 완전히 대기 연결에서 무시, 언급으로


나는 const & 부분입니다 테스트에서 확인할 수 있습니다. 연결된 각 슬롯은 객체의 새로운 사본을 얻습니다. 이것은 매우 불행합니다. : (

추가 테스트를 통해 슬롯에는 &이 사용되었지만 비정상적인 방식으로 나타납니다. 개체의 복사본은 대기중인 연결에 대해 생성되지만 참조를 사용하지 않으면 다른 복사본이 생성됩니다.

따라서 connect은 모두 대기열에있는 연결에 대한 데이터 복사를 끝내기는하지만 참조가 여전히 도움이됩니다. 또한 몇 개의 신호가 로컬 (동일한 스레드)로 보내지는 경우 피할 수 있습니다 더 많은 복사.

+1

1) qRegisterMetaType() alltogether에서 문자열 인수를 생략 할 수 있어야합니다. 2) const ref는 신호/슬롯과 메타 타입에 대해서는 절대 필요하지 않습니다. 또한 const ref. 값을 전달하는 것은 시그널/슬롯 메커니즘과 같습니다 : 시그널 void 신호 (const T &)를 SIGNAL (시그널 (const T &)) 또는 SIGNAL (시그널 (T))을 통해 연결할 수 있으며, 시그니처는 "signal T) "어쨌든. 예 : 마샬링 된 경우 대기열에있는 연결의 경우 값은 const ref를 저장하지 않고 복사하여 저장합니다. –

+0

@Frank, 큐잉을 위해 나는 복사본을 가져가는 것이 좋습니다. 나는 수신기로 파견하는 것에 관심이있다. 레퍼런스가있는 신호에 많은 슬롯을 연결하면 동일한 객체에 대한 참조가 모든 경우에 사용됩니다 (즉, 동일한 스레드 내의 모든 슬롯). –

+1

qa, 난 그냥 소스를 확인하고 Qt는 각각의 대기열에있는 연결에 대한 복사본을 만듭니다, 즉, 각 수신기에 대한 것 같습니다.원하는 경우 발신자를 통해 반복되는 QMetaObject :: activate()와 qobject.cpp의 실제 복사를 수행하는 QMetaObject :: queued_activate()를 확인하십시오. –

2

Argument type for Qt signal and slot, does const reference qualifiers matters?의 대답 중 하나에 따르면 대기중인 연결의 경우 h와 관계없이 개체가 복사됩니다. 당신은 신호와 슬롯을 연결합니다.

여러 스레드를 사용 중이므로 연결이 대기열에 있습니다. 뮤텍스 비용을 두려워하는 경우 SomeClass *를 직접 사용해보십시오.

+0

복사 생성자 (또는 연산자 =)를 사용하는 한 스레드를 통해 복사하는 것은 완전히 괜찮습니다. 한 스레드 내에서 모든 수신기에 복사하는 것을 원하지 않습니다. –

0

완벽을 기하기 위해 Qt에는 std :: shared_ptr과 똑같이 동작하는 QSharedPointer이라는 자체 공유 포인터 구현이 있다고 언급해야한다고 생각합니다. 결국에는 인수 유형을 등록해야합니다.

관련 문제