std::unique_ptr operator[] 与 raw ptr 动态数组 operator[]
std::unique_ptr operator[] vs. raw ptr dynamic array operator[]
我有以下代码示例:
void foo(int size)
{
std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t>(size);
for(int i = 0; i < size; i += 2)
{
data[i] = 1;
data[i + 1] = 2;
}
}
实际代码进行实际计算,但这对这个问题无关紧要,为简单起见已将其删除。
在编译和 运行 启用优化的代码时,一切都运行良好并且运行速度很快。
然而,当 运行 没有任何优化时,这段代码比:
慢得多
void foo(int size)
{
std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t>(size);
uint8_t* dataPtr = data.get();
for(int i = 0; i < size; i += 2)
{
dataPtr[i] = 1;
dataPtr[i + 1] = 2;
}
}
为了对此进行更多研究,我 运行 通过编译器资源管理器 (godbolt.org) 使用此动态数组对索引运算符进行了多种变体。
使用 clang 和 -O3 优化进行编译,所有变体都会产生相同的程序集。
然而,在没有任何优化的情况下编译,unique_ptr 唯一的示例调用了 unique_ptr operator[],这似乎是导致速度下降的原因。
为什么 unique_ptr 的 operator[] 没有优化会慢很多?从文档中我看到 operator[] 应该等同于 unique_ptr.get()[]。
它是否在没有优化的情况下进行一些安全检查?如果有,是哪些?
如果不进行优化,调用 operator[]
并将索引作为参数传递会产生开销。通过优化,编译器可以内联整个函数以避免调用函数的开销(并且由于它导致相同的汇编,你已经知道性能将是相同的)。
这是 profiling/benchmarking 没有优化会导致错误结果的众多原因之一:零成本抽象将产生在您的生产构建中通常不会产生的成本。
我有以下代码示例:
void foo(int size)
{
std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t>(size);
for(int i = 0; i < size; i += 2)
{
data[i] = 1;
data[i + 1] = 2;
}
}
实际代码进行实际计算,但这对这个问题无关紧要,为简单起见已将其删除。
在编译和 运行 启用优化的代码时,一切都运行良好并且运行速度很快。 然而,当 运行 没有任何优化时,这段代码比:
慢得多void foo(int size)
{
std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t>(size);
uint8_t* dataPtr = data.get();
for(int i = 0; i < size; i += 2)
{
dataPtr[i] = 1;
dataPtr[i + 1] = 2;
}
}
为了对此进行更多研究,我 运行 通过编译器资源管理器 (godbolt.org) 使用此动态数组对索引运算符进行了多种变体。 使用 clang 和 -O3 优化进行编译,所有变体都会产生相同的程序集。 然而,在没有任何优化的情况下编译,unique_ptr 唯一的示例调用了 unique_ptr operator[],这似乎是导致速度下降的原因。
为什么 unique_ptr 的 operator[] 没有优化会慢很多?从文档中我看到 operator[] 应该等同于 unique_ptr.get()[]。 它是否在没有优化的情况下进行一些安全检查?如果有,是哪些?
如果不进行优化,调用 operator[]
并将索引作为参数传递会产生开销。通过优化,编译器可以内联整个函数以避免调用函数的开销(并且由于它导致相同的汇编,你已经知道性能将是相同的)。
这是 profiling/benchmarking 没有优化会导致错误结果的众多原因之一:零成本抽象将产生在您的生产构建中通常不会产生的成本。