Programing

C ++ 라이브러리 및 프레임 워크가 스마트 포인터를 사용하지 않는 이유는 무엇입니까?

crosscheck 2020. 6. 6. 08:17
반응형

C ++ 라이브러리 및 프레임 워크가 스마트 포인터를 사용하지 않는 이유는 무엇입니까?


나는 몇 가지 기사에서 원시 포인터를 거의 사용해서는 안된다는 것을 읽었습니다. 대신 범위 또는 공유 포인터 여부에 관계없이 항상 스마트 포인터 안에 싸야합니다.

그러나 Qt, wxWidgets 및 Boost와 같은 라이브러리와 같은 프레임 워크는 전혀 사용하지 않는 것처럼 스마트 포인터를 반환하거나 기대하지 않습니다. 대신 원시 포인터를 반환하거나 기대합니다. 그 이유가 있습니까? 퍼블릭 API를 작성할 때 스마트 포인터에서 멀리 떨어져 있어야하는 이유는 무엇입니까?

많은 주요 프로젝트에서이를 피하려고 할 때 왜 스마트 포인터가 권장되는지 궁금합니다.


표준 스마트 포인터가 출현하기 전에 많은 라이브러리가 작성되었다는 사실 외에도 가장 큰 이유는 표준 C ++ 응용 프로그램 이진 인터페이스 (ABI)가 없기 때문일 것입니다.

헤더 전용 라이브러리를 작성하는 경우 스마트 포인터 및 표준 컨테이너를 마음의 내용으로 전달할 수 있습니다. 소스는 컴파일 타임에 라이브러리에서 사용할 수 있으므로 구현이 아닌 인터페이스의 안정성에만 의존합니다.

그러나 표준 ABI가 없기 때문에 일반적으로 이러한 개체를 모듈 경계를 넘어 안전하게 전달할 수 없습니다 . GCC shared_ptr는 MSVC shared_ptr와 다를 수 있으며 인텔과 다를 수 있습니다 shared_ptr. 동일한 컴파일러를 사용 하더라도 이러한 클래스는 버전간에 이진 호환이 보장되지 않습니다.

결론은 사전 빌드 된 라이브러리 버전 을 배포 하려면 신뢰할 수있는 표준 ABI가 필요하다는 것입니다. C에는 하나도 없지만 컴파일러 공급 업체는 주어진 플랫폼에 대한 C 라이브러리 간의 상호 운용성에 대해 매우 능숙합니다. 사실상 표준이 있습니다.

상황은 C ++에 적합하지 않습니다. 개별 컴파일러는 자체 바이너리 간의 상호 운용성을 처리 할 수 ​​있으므로 지원되는 모든 컴파일러 (일반적으로 GCC 및 MSVC)의 버전을 배포 할 수 있습니다. 그러나 이것에 비추어 볼 때 대부분의 라이브러리는 C 인터페이스를 내보내므로 원시 포인터를 의미합니다.

그러나 비 라이브러리 코드는 일반적으로 원시보다 스마트 포인터를 선호해야합니다.


여러 가지 이유가있을 수 있습니다. 그중 몇 가지를 나열하려면 :

  1. 스마트 포인터는 최근에 표준의 일부가되었습니다. 그때까지 그들은 다른 도서관의 일부였습니다
  2. 주요 용도는 메모리 누수를 방지하는 것입니다. 많은 라이브러리에는 자체 메모리 관리 기능이 없습니다. 일반적으로 유틸리티와 API를 제공합니다
  3. 그것들은 실제로 포인터가 아닌 객체이기 때문에 래퍼로 ​​구현됩니다. 원시 포인터와 비교하여 추가 시간 / 공간 비용이 있습니다. 라이브러리 사용자는 이러한 오버 헤드를 원하지 않을 수 있습니다

편집 : 스마트 포인터를 사용하는 것은 개발자의 선택입니다. 다양한 요인에 따라 다릅니다.

  1. 성능이 중요한 시스템에서는 오버 헤드를 생성하는 스마트 포인터를 사용하지 않을 수 있습니다

  2. 이전 버전과의 호환성이 필요한 프로젝트 인 경우 C ++ 11 전용 기능이있는 스마트 포인터를 사용하지 않을 수 있습니다.

Edit2 아래 통로로 인해 24 시간 동안 여러 다운 보트 문자열이 있습니다. 아래는 답변이 아닌 추가 제안이지만 답변이 다운 투표 된 이유를 이해하지 못합니다.
그러나 C ++에서는 항상 옵션을 쉽게 열 수 있습니다. :) 예

template<typename T>
struct Pointer {
#ifdef <Cpp11>
  typedef std::unique_ptr<T> type;
#else
  typedef T* type;
#endif
};

그리고 코드에서 다음과 같이 사용하십시오.

Pointer<int>::type p;

똑똑한 포인터와 원시 포인터가 다르다고 말하는 사람들에게는 동의합니다. 위의 코드는 단지 하나와 교환 가능한 코드를 작성할 수 있는 아이디어 일뿐입니다. #define이것은 강제 가 아닙니다 .

예를 들어, T*명시 적으로 삭제해야하지만 스마트 포인터는 그렇지 않습니다. Destroy()이를 처리하기 위해 템플릿 만들 수 있습니다 .

template<typename T>
void Destroy (T* p)
{
  delete p;
}
template<typename T>
void Destroy (std::unique_ptr<T> p)
{
  // do nothing
}

그것을 다음과 같이 사용하십시오 :

Destroy(p);

같은 방식으로, 원시 포인터의 경우 직접 복사 할 수 있고 스마트 포인터의 경우 특수 작업을 사용할 수 있습니다.

Pointer<X>::type p = new X;
Pointer<X>::type p2(Assign(p));

다음 Assign()과 같습니다

template<typename T>
T* Assign (T *p)
{
  return p;
}
template<typename T>
... Assign (SmartPointer<T> &p)
{
  // use move sematics or whateve appropriate
}

스마트 포인터에는 두 가지 문제가 있습니다 (pre C ++ 11).

  • 비표준이므로 각 라이브러리는 자체적으로 재발견되는 경향이 있습니다 (NIH syndrom 및 종속성 문제)
  • 잠재적 비용

기본 은 비용이없는 점에서 스마트 포인터는 것입니다 unique_ptr. 불행히도 최근에 등장한 C ++ 11 이동 의미가 필요합니다. 다른 모든 스마트 포인터는 비용 (이 shared_ptr, intrusive_ptr) 또는 (이상적인 의미보다 적은있다 auto_ptr).

C ++ 11을 모퉁이에 가져 std::unique_ptr가면 마침내 끝났다고 생각하게 될 것입니다 ... 나는 낙관적이지 않습니다.

Only a few major compilers implement most of C++11, and only in their recent versions. We can expect major libraries such as QT and Boost to be willing to retain compatibility with C++03 for a while, which somewhat precludes the wide adoption of the new and shiny smart pointers.


You shouldn't stay away from smart pointers, they have their use especially in applications where you have to pass a object around.

Libraries tend to either just return a value or populate a object. They don't usually have objects that need to be used in a lot of places, so there is no need for them to use smart pointers (at least not in their interface, they may use them internally).

I could take as example a library we have been working on, where after a few months of development I realized we only used pointers and smart pointers in a few classes (3-5% of all classes).

Passing variables by reference was enough in most places, we used smart pointers whenever we had a object that could be null, and raw pointers when a library that we used forced us to.

Edit (I can't comment because of my reputation): passing variables by reference is very flexible: if you want the object to be readonly you can use a const reference (you can still do some nasty casts to be able to write the object) but you get the maximum of protection possible (it's the same with smart pointers). But I do agree that it's much nicer to just return the object.


Qt pointlessly re-invented many parts of the Standard library in an attempt to become Java. I believe that it does actually have its own smart pointers now, but in general, it is hardly a pinnacle of design. wxWidgets, as far as I'm aware, was designed long before usable smart pointers were written.

As for Boost, I fully expect that they use smart pointers wherever appropriate. You might have to be more specific.

In addition, don't forget that smart pointers exist to enforce ownership. If the API has no ownership semantics, then why use a smart pointer?


Good question. I don't know the specific articles to which you refer, but I have read similar things from time to time. My suspicion is that the writers of such articles tend to harbor a bias against C++-style programming. If the writer programs in C++ only when he must, then returns to Java or such as soon as he can, then he doesn't really share the C++ mindset.

One suspects that some or most of the same writers prefer garbage-collecting memory managers. I don't, but I think differently than they do.

Smart pointers are great, but they have to keep reference counts. The keeping of reference counts bears costs -- often modest costs, but costs nonetheless -- at runtime. There is nothing wrong with saving these costs by using bare pointers, especially if the pointers are managed by destructors.

One of the excellent things about C++ is its support for embedded-systems programming. The use of bare pointers is part of that.

Update: A commenter has correctly observed that C++'s new unique_ptr (available since TR1) does not count references. The commenter also has a different definition of "smart pointer" than I have in mind. He may be right about the definition.

Further update: The comment thread below is illuminating. All of it is recommended reading.


There are also other types of smart pointers. You might want a specialized smart pointer for something like network replication (one that detects if it's accessed and sends any modifications to the server or some such), keeps a history of changes, marks the fact that it was accessed so it can be investigated when you save data to disk and so on. Not sure if doing that in the pointer is the best solution but using the built in smart pointer types in libraries could result in people being locked into them and loosing the flexibility.

People can have all kinds of different memory management requirements and solutions beyond smart pointers. I might want to manage memory myself, I could be allocating space for things in a memory pool so it's allocated in advance and not at runtime (useful for games). I might be using a garbage collected implementation of C++ (C++11 makes this possible although none exist yet). Or maybe I'm just not doing anything advanced enough to worry about bothering with them, I can know that I'm not going to forget to uninitialized objects and so on. Maybe I'm just confident in my ability to manage memory without the pointer crutch.

Integration with C is another issue too.

Another issue is smart pointers are part of the STL. C++ is designed to be usable without the STL.


It also depends on what domain you work in. I write game engines for a living, we avoid boost like the plague, in games the overhead of boost isn't acceptable. In our core engine we ended up writing our own version of stl (Much like the ea stl).

If i was to write a forms application, i might consider using smart pointers; but once memory management is second nature not having granular control over memory becomes quiet annoying.

참고URL : https://stackoverflow.com/questions/10334511/why-do-c-libraries-and-frameworks-never-use-smart-pointers

반응형