如果大小保持不变,编译器会优化每次循环构造新对象吗?

问题描述 投票:0回答:1

在我编写的一些代码中,一个新的 FenwickTree 是由向量

ind
构造的,每个循环都保持相同的大小。 FenwickTree 的大小与输入向量相同。编译器是否会在循环开始时不重复优化构造对象并分配内存,然后在循环结束时销毁对象?我更熟悉 C,其中内存管理是显式的。

示例

#include <vector>
#include <iostream>

struct fenwick_tree
{
    size_t len; // 0-based len
    std::vector<int> t; // 1-based tree, indexes [1:len]

    fenwick_tree(std::vector<int> const &a) :
    len(a.size()), t(len + 1, 0) 
    {
        for (size_t i = 0; i < len; ++i)
            add_to(i, a[i]);
    }

    // 0-based input
    int sum_to(size_t r) const
    {
        int s = 0;
        for (++r; r > 0; r -= r & -r)
            s += t[r];
        return s;
    }

    // 0-based input
    void add_to(size_t i, int delta)
    {
        for (++i; i <= len; i += i & -i)
            t[i] += delta;
    }
};

int main()
{
    std::vector<int> ind(10, 10);
    for (int i = 1; i < 10; ++i)
    {
        ind.assign(10, 10*i);
        auto fen = fenwick_tree(ind);

        std::cout << fen.sum_to(9) << std::endl;
    }
}

这是ltrace的结果。我可以看到memset和flush,但我不知道是否

_ZNSt8ios_base4InitC1Ev(0x58659f9b8151, 0x7ffd6d84bd48, 0x7ffd6d84bd58, 0x58659f9b7d30) = 0x72f4c90224b8
__cxa_atexit(0x72f4c92bf840, 0x58659f9b8151, 0x58659f9b8008, 0x72f4c942ada0)          = 0
_Znwm(40, 0x7ffd6d84bd48, 0x7ffd6d84bd58, 0x58659f9b7d38)                             = 0x5865aab3ceb0
_Znwm(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
_ZNSolsEi(0x58659f9b8040, 100, 2, 10)                                                 = 0x58659f9b8040
_ZNSo3putEc(0x58659f9b8040, 10, 0x72f4c9423370, 0x7ffd6d84bac8100
)                       = 0x58659f9b8040
_ZNSo5flushEv(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
_ZdlPvm(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
_Znwm(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
_ZNSolsEi(0x58659f9b8040, 200, 2, 20)                                                 = 0x58659f9b8040
_ZNSo3putEc(0x58659f9b8040, 10, 0x72f4c9423370, 3122200
)                                 = 0x58659f9b8040
_ZNSo5flushEv(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
_ZdlPvm(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
_Znwm(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
_ZNSolsEi(0x58659f9b8040, 300, 2, 30)                                                 = 0x58659f9b8040
_ZNSo3putEc(0x58659f9b8040, 10, 0x72f4c9423370, 3123300
)                                 = 0x58659f9b8040
_ZNSo5flushEv(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
_ZdlPvm(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
_Znwm(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
_ZNSolsEi(0x58659f9b8040, 400, 2, 40)                                                 = 0x58659f9b8040
_ZNSo3putEc(0x58659f9b8040, 10, 0x72f4c9423370, 3124400
)                                 = 0x58659f9b8040
_ZNSo5flushEv(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
_ZdlPvm(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
_Znwm(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
_ZNSolsEi(0x58659f9b8040, 500, 2, 50)                                                 = 0x58659f9b8040
_ZNSo3putEc(0x58659f9b8040, 10, 0x72f4c9423370, 3125500
)                                 = 0x58659f9b8040
_ZNSo5flushEv(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
_ZdlPvm(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
_Znwm(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
_ZNSolsEi(0x58659f9b8040, 600, 2, 60)                                                 = 0x58659f9b8040
_ZNSo3putEc(0x58659f9b8040, 10, 0x72f4c9423370, 3126600
)                                 = 0x58659f9b8040
_ZNSo5flushEv(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
_ZdlPvm(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
_Znwm(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
_ZNSolsEi(0x58659f9b8040, 700, 2, 70)                                                 = 0x58659f9b8040
_ZNSo3putEc(0x58659f9b8040, 10, 0x72f4c9423370, 3127700
)                                 = 0x58659f9b8040
_ZNSo5flushEv(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
_ZdlPvm(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
_Znwm(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
_ZNSolsEi(0x58659f9b8040, 800, 2, 80)                                                 = 0x58659f9b8040
_ZNSo3putEc(0x58659f9b8040, 10, 0x72f4c9423370, 3128800
)                                 = 0x58659f9b8040
_ZNSo5flushEv(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
_ZdlPvm(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
_Znwm(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
_ZNSolsEi(0x58659f9b8040, 900, 2, 90)                                                 = 0x58659f9b8040
_ZNSo3putEc(0x58659f9b8040, 10, 0x72f4c9423370, 3129900
)                                 = 0x58659f9b8040
_ZNSo5flushEv(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
_ZdlPvm(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
_ZdlPvm(0x5865aab3ceb0, 40, 0x5865aab3c, 2)                                           = 0
+++ exited (status 0) +++

来自demangler.com

std::ios_base::Init::Init()(0x58659f9b8151, 0x7ffd6d84bd48, 0x7ffd6d84bd58, 0x58659f9b7d30) = 0x72f4c90224b8
__cxa_atexit(0x72f4c92bf840, 0x58659f9b8151, 0x58659f9b8008, 0x72f4c942ada0)          = 0
operator new(unsigned long)(40, 0x7ffd6d84bd48, 0x7ffd6d84bd58, 0x58659f9b7d38)                             = 0x5865aab3ceb0
operator new(unsigned long)(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
std::ostream::operator<<(int)(0x58659f9b8040, 100, 2, 10)                                                 = 0x58659f9b8040
std::ostream::put(char)(0x58659f9b8040, 10, 0x72f4c9423370, 0x7ffd6d84bac8100
)                       = 0x58659f9b8040
std::ostream::flush()(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
operator delete(void*, unsigned long)(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
operator new(unsigned long)(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
std::ostream::operator<<(int)(0x58659f9b8040, 200, 2, 20)                                                 = 0x58659f9b8040
std::ostream::put(char)(0x58659f9b8040, 10, 0x72f4c9423370, 3122200
)                                 = 0x58659f9b8040
std::ostream::flush()(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
operator delete(void*, unsigned long)(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
operator new(unsigned long)(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
std::ostream::operator<<(int)(0x58659f9b8040, 300, 2, 30)                                                 = 0x58659f9b8040
std::ostream::put(char)(0x58659f9b8040, 10, 0x72f4c9423370, 3123300
)                                 = 0x58659f9b8040
std::ostream::flush()(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
operator delete(void*, unsigned long)(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
operator new(unsigned long)(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
std::ostream::operator<<(int)(0x58659f9b8040, 400, 2, 40)                                                 = 0x58659f9b8040
std::ostream::put(char)(0x58659f9b8040, 10, 0x72f4c9423370, 3124400
)                                 = 0x58659f9b8040
std::ostream::flush()(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
operator delete(void*, unsigned long)(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
operator new(unsigned long)(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
std::ostream::operator<<(int)(0x58659f9b8040, 500, 2, 50)                                                 = 0x58659f9b8040
std::ostream::put(char)(0x58659f9b8040, 10, 0x72f4c9423370, 3125500
)                                 = 0x58659f9b8040
std::ostream::flush()(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
operator delete(void*, unsigned long)(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
operator new(unsigned long)(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
std::ostream::operator<<(int)(0x58659f9b8040, 600, 2, 60)                                                 = 0x58659f9b8040
std::ostream::put(char)(0x58659f9b8040, 10, 0x72f4c9423370, 3126600
)                                 = 0x58659f9b8040
std::ostream::flush()(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
operator delete(void*, unsigned long)(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
operator new(unsigned long)(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
std::ostream::operator<<(int)(0x58659f9b8040, 700, 2, 70)                                                 = 0x58659f9b8040
std::ostream::put(char)(0x58659f9b8040, 10, 0x72f4c9423370, 3127700
)                                 = 0x58659f9b8040
std::ostream::flush()(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
operator delete(void*, unsigned long)(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
operator new(unsigned long)(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
std::ostream::operator<<(int)(0x58659f9b8040, 800, 2, 80)                                                 = 0x58659f9b8040
std::ostream::put(char)(0x58659f9b8040, 10, 0x72f4c9423370, 3128800
)                                 = 0x58659f9b8040
std::ostream::flush()(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
operator delete(void*, unsigned long)(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
operator new(unsigned long)(44, 11, 0x5865aab3ced8, 0x5865aab3ced8)                                         = 0x5865aab3cee0
memset(0x5865aab3cee0, '\0', 44)                                                      = 0x5865aab3cee0
std::ostream::operator<<(int)(0x58659f9b8040, 900, 2, 90)                                                 = 0x58659f9b8040
std::ostream::put(char)(0x58659f9b8040, 10, 0x72f4c9423370, 3129900
)                                 = 0x58659f9b8040
std::ostream::flush()(0x58659f9b8040, 0x5865aab3cf20, 0x72f4c9423370, 0x72f4c8f14887)         = 0x58659f9b8040
operator delete(void*, unsigned long)(0x5865aab3cee0, 44, 0x72f4c9423370, 3072)                                     = 0
operator delete(void*, unsigned long)(0x5865aab3ceb0, 40, 0x5865aab3c, 2)                                           = 0
    exited (status 0)    

看起来好像调用了一堆new和delete?

c++ constructor ltrace
1个回答
0
投票

编译器优化

sizeof(fen)
的堆栈分配。这是非常微不足道的,以至于一些编译器甚至在调试模式下也会这样做;这甚至不是他们内部设计的优化步骤。

编译器不会优化

fenwick_tree::t
的分配。向量的长度可以在运行时变化,并且它不是
sizeof(fenwick_tree)
的一部分。然而,标准库实现通常会回收内存。这种回收可以发生在内部
operator new
,因此痕迹仍然可见。

© www.soinside.com 2019 - 2024. All rights reserved.