优化编译器是否可以从std :: unique_ptr中删除所有运行时成本?

She*_*evy 6 c++ optimization unique-ptr c++11

std::unique_ptrhttp://en.cppreference.com/w/cpp/memory/unique_ptr上阅读,我的天真印象是,一个足够聪明的编译器可以unique_ptr用裸指针替换正确的使用,并deleteunique_ptrs被破坏时放入.实际情况如此吗?如果是这样,任何主流优化编译器实际上都这样做了吗?如果没有,是否可以编写一些具有部分/全部unique_ptr编译时安全优势的东西,这些优点可以优化以便没有运行时成本(空间或时间)?

注意那些(正确地)担心过早优化:这里的答案不会阻止我使用std::unique_ptr,我只是好奇它是一个非常棒的工具还是只是一个很棒的工具.

编辑2013/07/21美国东部时间20:07:

好的,所以我测试了以下程序(请告诉我这是否有问题):

#include <climits>
#include <chrono>
#include <memory>
#include <iostream>

static const size_t iterations = 100;

int main (int argc, char ** argv) {
    std::chrono::steady_clock::rep smart[iterations];
    std::chrono::steady_clock::rep dumb[iterations];
    volatile int contents;
    for (size_t i = 0; i < iterations; i++) {
        auto start = std::chrono::steady_clock::now();
        {
            std::unique_ptr<int> smart_ptr(new int(5));
            for (unsigned int j = 0; j < UINT_MAX; j++)
                contents = *smart_ptr;
        }
        auto middle = std::chrono::steady_clock::now();
        {
            int *dumb_ptr = new int(10);
            try {
                for (unsigned int j = 0; j < UINT_MAX; j++)
                    contents = *dumb_ptr;
                delete dumb_ptr;
            } catch (...) {
                delete dumb_ptr;
                throw;
            }
        }
        auto end = std::chrono::steady_clock::now();
        smart[i] = (middle - start).count();
        dumb[i] = (end - middle).count();
    }
    std::chrono::steady_clock::rep smartAvg;
    std::chrono::steady_clock::rep dumbAvg;
    for (size_t i = 0; i < iterations; i++) {
        smartAvg += smart[i];
        dumbAvg += dumb[i];
    }
    smartAvg /= iterations;
    dumbAvg /= iterations;

    std::cerr << "Smart: " << smartAvg << " Dumb: " << dumbAvg << std::endl;
    return contents;
}
Run Code Online (Sandbox Code Playgroud)

使用g ++编译4.7.3使用g++ --std=c++11 -O3 test.cc得到Smart: 1130859 Dumb: 1130005的,这意味着在智能指针是哑指针,这是几乎肯定噪声的0.076%的范围内.

Mat*_*son 5

这肯定是我对任何合理的编译器的期望,因为它只是一个简单指针和析构函数的包装器delete,所以编译器为以下代码生成的机器代码:

x *p = new X;
... do stuff with p. 
delete p; 
Run Code Online (Sandbox Code Playgroud)

unique_ptr<X> p(new X);
... do stuff with p; 
Run Code Online (Sandbox Code Playgroud)

将完全相同的代码.

  • 这是关于其余代码的异常!(所以我应该说'x*p = new X; try {/*...*/} catch(...){delete p; throw;}`.) (2认同)