一个空的别名shared_ptr是否删除shared_ptr的一个很好的替代方案?

Joh*_*itb 11 c++ shared-ptr c++11

有时我需要shared_ptr具有no-op删除器的shared_ptr实例,因为API需要一个它想要在有限时间内存储的实例但我得到一个原始指针,我不允许拥有的时间比我正在运行的时间大对于.

对于这种情况,我一直用一个空操作删除器,如[](const void *){},但今天我发现还有另一种选择到,使用(或滥用?)的混叠构造shared_ptr:

void f(ExpectedClass *ec) {
   std::shared_ptr<ExpectedClass> p(std::shared_ptr<void>(), ec);
   assert(p.use_count() == 0 && p.get() != nullptr);
   apiCall(p);
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,更好的方法是什么?为什么?性能期望是否相同?使用no-op删除器,我希望为删除器和引用计数的存储支付一些费用,当使用带有空的别名构造函数时似乎不是这种情况shared_ptr.

Col*_*mbo 6

关于性能,以下基准显示不稳定的数字:

#include <chrono>
#include <iostream>
#include <limits>
#include <memory>

template <typename... Args>
auto test(Args&&... args) {
    using clock = std::chrono::high_resolution_clock;
    auto best = clock::duration::max();

    for (int outer = 1; outer < 10000; ++outer) {
        auto now = clock::now();

        for (int inner = 1; inner < 20000; ++inner)
            std::shared_ptr<int> sh(std::forward<Args>(args)...);

        auto time = clock::now()-now;
        if (time < best) {
            best = time;
            outer = 1;
        }
    }

    return best.count();
}

int main()
{
    int j;

    std::cout << "With aliasing ctor: " << test(std::shared_ptr<void>(), &j) << '\n'
              << "With empty deleter: " << test(&j, [] (auto) {});
}
Run Code Online (Sandbox Code Playgroud)

在我的机器上输出clang++ -march=native -O2:

With aliasing ctor: 11812
With empty deleter: 651502
Run Code Online (Sandbox Code Playgroud)

具有相同选项的GCC提供了更大的比率,5921:465794.
并且Clang的-stdlib=libc++收益率高达12:613175.

  • @IlyaPopov不,默认构建shared_ptr不会分配任何东西. (2认同)

Jar*_*d42 1

快速板凳与

#include <memory>

static void aliasConstructor(benchmark::State& state) {
  for (auto _ : state) {
    int j = 0;
    std::shared_ptr<int> ptr(std::shared_ptr<void>(), &j);
    benchmark::DoNotOptimize(ptr);
  }
}

BENCHMARK(aliasConstructor);

static void NoOpDestructor(benchmark::State& state) {
  for (auto _ : state) {
    int j = 0;
    std::shared_ptr<int> ptr(&j, [](int*){});
    benchmark::DoNotOptimize(ptr);
  }
}

BENCHMARK(NoOpDestructor);
Run Code Online (Sandbox Code Playgroud)

给出

所以别名构造函数获胜。