멤버 변수를 클래스 멤버로 참조
제 직장에서는이 스타일이 광범위하게 사용되는 것을 봅니다.
#include <iostream>
using namespace std;
class A
{
public:
A(int& thing) : m_thing(thing) {}
void printit() { cout << m_thing << endl; }
protected:
const int& m_thing; //usually would be more complex object
};
int main(int argc, char* argv[])
{
int myint = 5;
A myA(myint);
myA.printit();
return 0;
}
이 관용구를 설명하는 이름이 있습니까? 나는 그것이 크고 복잡한 객체를 복사하는 데 따르는 큰 오버 헤드를 방지하는 것이라고 가정하고 있습니다.
이것은 일반적으로 좋은 습관입니까? 이 접근 방식에 함정이 있습니까?
이 관용구를 설명하는 이름이 있습니까?
UML에서는 집계라고합니다. 멤버 객체가 참조 클래스에 의해 소유 되지 않는다는 점에서 구성과 다릅니다 . C ++에서는 참조 또는 포인터를 통해 두 가지 방법으로 집계를 구현할 수 있습니다.
나는 그것이 크고 복잡한 객체를 복사하는 데 따르는 큰 오버 헤드를 방지하는 것이라고 가정하고 있습니다.
아니요, 이걸 사용하는 것은 정말 나쁜 이유입니다. 집계의 주된 이유는 포함 된 개체가 포함 된 개체의 소유가 아니므로 해당 수명이 바인딩되지 않기 때문입니다. 특히 참조 된 개체 수명은 참조하는 개체 수명보다 길어야합니다. 훨씬 더 일찍 만들어 졌을 수 있으며 컨테이너의 수명이 끝난 후에도 살 수 있습니다. 그 외에도 참조 된 객체의 상태는 클래스에 의해 제어되지 않지만 외부 적으로 변경 될 수 있습니다. 참조가 아닌 const
경우 클래스는 외부에있는 객체의 상태를 변경할 수 있습니다.
이것은 일반적으로 좋은 습관입니까? 이 접근 방식에 함정이 있습니까?
디자인 도구입니다. 어떤 경우에는 좋은 생각이 될 것이고 어떤 경우에는 그렇지 않을 것입니다. 가장 일반적인 함정은 참조를 보유한 개체의 수명이 참조 된 개체의 수명을 초과해서는 안된다는 것입니다. 둘러싸는 객체가 참조 된 객체가 파괴 된 후 참조를 사용하는 경우 정의되지 않은 동작이 발생합니다. 일반적으로 집계보다 컴포지션을 선호하는 것이 좋지만 필요한 경우 다른 도구만큼 좋은 도구입니다.
생성자 주입을 통한 종속성 주입 이라고합니다 . 클래스 A
는 해당 생성자에 대한 인수로 종속성을 가져오고 종속 클래스에 대한 참조를 전용 변수로 저장합니다.
wikipedia에 흥미로운 소개가 있습니다.
const 정확성을 위해 다음과 같이 작성합니다.
using T = int;
class A
{
public:
A(const T &thing) : m_thing(thing) {}
// ...
private:
const T &m_thing;
};
그러나이 클래스의 문제점은 임시 객체에 대한 참조를 허용한다는 것입니다.
T t;
A a1{t}; // this is ok, but...
A a2{T()}; // ... this is BAD.
추가하는 것이 더 좋습니다 (적어도 C ++ 11 필요).
class A
{
public:
A(const T &thing) : m_thing(thing) {}
A(const T &&) = delete; // prevents rvalue binding
// ...
private:
const T &m_thing;
};
어쨌든 생성자를 변경하면 :
class A
{
public:
A(const T *thing) : m_thing(*thing) { assert(thing); }
// ...
private:
const T &m_thing;
};
임시에 대한 포인터가 없다는 것은 거의 보장 됩니다 .
또한 생성자가 포인터를 사용하기 때문에 사용자가 A
전달하는 객체의 수명에주의를 기울여야한다는 것이 사용자에게 더 분명합니다
.
관련 주제는 다음과 같습니다.
이 관용구를 설명하는 이름이 있습니까?
There is no name for this usage, it is simply known as "Reference as class member".
I am assuming it is to prevent the possibly large overhead of copying a big complex object?
Yes and also scenarios where you want to associate the lifetime of one object with another object.
Is this generally good practice? Are there any pitfalls to this approach?
Depends on your usage. Using any language feature is like "choosing horses for courses". It is important to note that every (almost all) language feature exists because it is useful in some scenario.
There are a few important points to note when using references as class members:
- You need to ensure that the referred object is guaranteed to exist till your class object exists.
- You need to initialize the member in the constructor member initializer list. You cannot have a lazy initialization, which could be possible in case of pointer member.
- The compiler will not generate the copy assignment
operator=()
and you will have to provide one yourself. It is cumbersome to determine what action your=
operator shall take in such a case. So basically your class becomes non-assignable. - References cannot be
NULL
or made to refer any other object. If you need reseating, then it is not possible with a reference as in case of a pointer.
For most practical purposes (unless you are really concerned of high memory usage due to member size) just having a member instance, instead of pointer or reference member should suffice. This saves you a whole lot of worrying about other problems which reference/pointer members bring along though at expense of extra memory usage.
If you must use a pointer, make sure you use a smart pointer instead of a raw pointer. That would make your life much easier with pointers.
Member references are usually considered bad. They make life hard compared to member pointers. But it's not particularly unsual, nor is it some special named idiom or thing. It's just aliasing.
C++ provides a good mechanism to manage the life time of an object though class/struct constructs. This is one of the best features of C++ over other languages.
When you have member variables exposed through ref or pointer it violates the encapsulation in principle. This idiom enables the consumer of the class to change the state of an object of A without it(A) having any knowledge or control of it. It also enables the consumer to hold on to a ref/pointer to A's internal state, beyond the life time of the object of A. This is bad design. Instead the class could be refactored to hold a ref/pointer to the shared object (not own it) and these could be set using the constructor (Mandate the life time rules). The shared object's class may be designed to support multithreading/concurrency as the case may apply.
ReferenceURL : https://stackoverflow.com/questions/12387239/reference-member-variables-as-class-members
'UFO ET IT' 카테고리의 다른 글
디버그 모드에서 실행되지 않는 경우에도 "디버거 연결 대기 중"표시 (0) | 2021.01.06 |
---|---|
AFNetworking으로 세션을 관리하는 방법은 무엇입니까? (0) | 2021.01.06 |
Pandas DataFrame에서 쉼표가있는 숫자 문자열을 부동 소수점으로 변환 (0) | 2021.01.06 |
'cordova build ios --release'를 사용하여 iPhone 앱을 배포 (.ipa 생성)하려면 어떻게해야합니까? (0) | 2021.01.06 |
매직 메서드를 통해 액세스되는 PhpStorm 필드 (0) | 2021.01.06 |