【问题标题】:c++ Allocating memory on real time without vectorc ++在没有向量的情况下实时分配内存
【发布时间】:2014-08-15 00:30:50
【问题描述】:

再次询问堆栈。我有一个数组,我希望始终保持最小大小,因为我必须通过互联网发送。问题是,在操作完成之前,程序无法知道最小大小是多少。这导致我不得不采取一些方法:使用向量,或者制作程序可能需要的最大长度的数组,然后它知道最小大小,用new 初始化一个指针并将数据放在那里。但是我不能使用向量,因为它们需要发送序列化,并且向量和序列化都有我不想要的开销。示例:

unsigned short data[1270], // the maximum size the operation could take is 1270 shorts
*packet; // pointer
int counter; //this is to count how big "packet" will be
//example of operation, wich of course is different from my program
// in this case the operation takes 6 bytes
while(true) {
  for (int i; i != 6; i++) {
     counter++; 
     data[i]= 1;
  }
  packet=new unsigned short[counter];
  for (int i; i!=counter; i++) {
    packet[i]=data[i];
  }
}

您可能已经注意到,此代码循环运行,因此问题可能是我反复重新初始化同一指针的方式。 这段代码的问题是,如果我这样做:

std::cout<<counter<<" "<<sizeof(packet)/sizeof(unsigned short)<<" ";

counter大小不一(一般从1到35),但是packet的大小总是2。我在new之前也试过delete [],但是没有解决问题。

这个问题也可能与代码的另一部分有关,但我只是在问:

我重复分配内存的方式对吗?

【问题讨论】:

  • 如果你想记录/存储/等。大小,使用std::size_t。
  • 为什么不只使用最大大小的数据缓冲区,只发送一部分呢?
  • 我的意思是当你使用套接字发送方法时。您不必指定缓冲区的大小。您可以指定要发送的包含在该缓冲区中的数据的大小。
  • vector 只是new[] 的包装器,IDK 应该是“向量需要序列化才能发送”的意思。向量没有任何开销,除非您考虑将 size 和 capacity 都存储为开销
  • 大量内存泄漏。每个new 都必须有一个delete。如果你一直分配内存并且从不释放它,你最终会使用它。

标签: c++ arrays sockets pointers vector


【解决方案1】:

在向编译器请求时不断添加std::vector,使堆内存中分配的大小不超过实际需要的数量:

std::vector<int> vec;
std::size_t const maxSize = 10;
for (std::size_t i; i != maxSize; ++i)
{
  vec.reserve(vec.size() + 1u);
  vec.push_back(1234); // whatever you're adding
}

我应该补充一点,我认为在正常情况下没有充分的理由这样做。这个“程序”的性能可能会受到严重阻碍而没有明显的好处。

【讨论】:

    【解决方案2】:

    您始终可以使用指针和重新分配。 C++ 是一种强大的语言,因为它的指针,你不需要使用数组。

    看看cplusplus entry on realloc。

    对于您的情况,您可以像这样使用它:

    new_packet = (unsigned short*) realloc (packet, new_size * sizeof(unsigned short));
    
    if (new_packet!=NULL) {
       packet = new_packet;
       for(int i ; i < new_size ; i++)
           packet[i] = new_values[i];
    }
    else {
       if( packet != NULL )
           free (packet);
       puts ("Error (re)allocating memory");
       exit (1);
    }
    

    【讨论】:

    • 我确实声明了。如果你看,在“[1270]”之后有一个逗号,而不是一个“;”。
    • 明天将阅读链接并通知您,在此先感谢。
    • 啊,好吧,没看到逗号!
    【解决方案3】:

    好的,我在您的逻辑中发现了一些问题。让我们从主要的开始:为什么你需要分配一个完整的新数组和data 中的内容的副本只是为了通过套接字发送它?这不像是发送一封信,send() 将传输信息的副本,而不是在网络上真正移动它。这样做完全没问题:

    send(socket, data, counter * sizeof(unsigned short), 0);
    

    那里。您不需要任何新指针。

    另外,我不知道你从哪里得到序列化的东西。向量基本上是自动调整大小的数组,一旦函数完成,它们也会从内存中删除。你可以这样做:

    std::vector<unsigned short> packet;
    packet.reserve(counter);
    for (std::size_t i = 0; i < counter; ++i)
        packet[i] = data[i];
    
    send(socket, &packet[0], packet.size() * sizeof(unsigned short), 0);
    

    甚至缩短为:

    std::vector<unsigned short> packet;
    for (std::size_t i = 0; i < counter; ++i)
        packet.push_back(data[i]);
    

    但是使用此选项,向量将调整counter 倍的大小,这会消耗性能。如果您有可用的信息,请始终先设置其大小。

    【讨论】:

    • 它几乎肯定不会调整counter 倍的大小。有时,log2(counter) 的可能性更大。
    • 如果对象packet 甚至不知道counter 的值,为什么会这样呢?仅当编译器进行一些优化时。
    • 实际上,它会调整counter 次的大小,但不会多次重新分配内存。因此,counter 的大小不会线性影响性能。
    猜你喜欢
    • 2017-08-19
    • 2015-12-08
    • 2021-08-28
    • 2021-12-02
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 2021-06-26
    • 2015-12-02
    相关资源
    最近更新 更多