C ++의 얕은 사본에 대한 질문
-
03-07-2019 - |
문제
int pointer 멤버 변수 "i"가있는 구조 "s"가 있다고 말합니다. s의 기본 생성자에서 i에 대한 힙에 메모리를 할당합니다. 나중에 코드의 다른 부분에서는 값별로 s 인스턴스를 일부 함수로 전달합니다. 여기서 얕은 사본을하고 있습니까? 사본 생성자 나 할당 연산자 등을 구현하지 않았다고 가정합니다.
해결책
@[don.neufeld.myopenid.com]이 말한 것을 후속하기 위해, 그것은 얕은 사본 일뿐 만 아니라 메모리 누출 또는 매달려있는 포인터입니다.
// memory leak (note that the pointer is never deleted)
class A
{
B *_b;
public:
A()
: _b(new B)
{
}
};
// dangling ptr (who deletes the instance?)
class A
{
B *_b;
public:
A()
... (same as above)
~A()
{
delete _b;
}
};
이를 해결하기 위해 몇 가지 방법이 있습니다.
원시 메모리 포인터를 사용하는 클래스에서 항상 사본 생성자 및 연산자 =를 구현하십시오.
class A
{
B *_b;
public:
A()
... (same as above)
~A()
...
A(const A &rhs)
: _b(new B(rhs._b))
{
}
A &operator=(const A &rhs)
{
B *b=new B(rhs._b);
delete _b;
_b=b;
return *this;
};
말할 것도없이, 이것은 큰 고통이며 올바르게 얻을 수있는 미묘함이 꽤 있습니다. 나는 내가 여기서 바로 그것을했다고 확신조차하지 않았고 나는 그것을 몇 번했다. 모든 멤버를 복사해야한다는 것을 잊지 마십시오. 나중에 새로운 멤버를 추가하면 추가하는 것을 잊지 마십시오!
클래스에서 카피 생성자와 연산자 = 비공개로 만드십시오. 이것은 "문 잠금"솔루션입니다. 간단하고 효과적이지만 때로는 과도하게 보호됩니다.
class A : public boost::noncopyable
{
...
};
원시 포인터를 사용하지 마십시오. 이것은 간단하고 효과적입니다. 여기에는 많은 옵션이 있습니다.
- 원시 문자 대신 문자열 클래스를 사용하십시오
- std :: auto_ptr, boost :: shared_ptr, boost :: scoped_ptr 사용
예시:
// uses shared_ptr - note that you don't need a copy constructor or op= -
// shared_ptr uses reference counting so the _b instance is shared and only
// deleted when the last reference is gone - admire the simplicity!
// it is almost exactly the same as the "memory leak" version, but there is no leak
class A
{
boost::shared_ptr<B> _b;
public:
A()
: _b(new B)
{
}
};
다른 팁
예, 그것은 얕은 사본입니다. 이제 S의 두 개의 사본 (발신자 중 하나, 하나는 스택에 매개 변수로)이 있으며 각 사본은 동일한 메모리 블록에 대한 포인터를 포함합니다.
당신은 두 개의 사본을 가질 것입니다 s
구조, 각각은 그들 자신의 것을 가질 것입니다 i
포인터, 그러나 둘 다 i
포인터는 메모리에서 동일한 주소를 가리키는 동일한 값을 갖습니다. 그렇습니다. 얕은 사본이됩니다.