草庐IT

c++ - 用于分配/释放 I/O 缓冲区的现代 C++ 习惯用法

coder 2023-05-03 原文

对于 I/O 工作,我需要将 N 个字节读入缓冲区。 N 在运行时(而不是编译时)是已知的。缓冲区大小永远不会改变。缓冲区被传递给其他例程来压缩、加密等:它只是一个字节序列,没有比这更高的了。

在 C 语言中,我将使用 malloc 分配缓冲区,然后在完成后使用 free 分配缓冲区。但是,我的代码是现代 C++,当然没有 malloc,并且很少有原始的 newdelete:我正在大量使用RAII 和 shared_ptr。然而,这些技术似乎都不适合这个缓冲区。它只是一个固定长度的字节缓冲区,用于接收 I/O 并使其内容可用。

是否有一个现代的 C++ 成语来优雅地表达这一点?或者,在这方面,我应该坚持使用好的 ol' malloc

最佳答案

基本上,您有两种主要的 C++ 方式选择:

  • std::vector
  • std::unique_ptr

我更喜欢第二个,因为您不需要 std::vector 中的所有自动调整大小的东西, 你不需要一个容器 - 你只需要一个缓冲区。

std::unique_ptr专门针对动态数组:std::unique_ptr<int[]>将调用 delete []在它的析构函数中,并将为您提供适当的operator [] .

如果你想要代码:

std::unique_ptr<char[]> buffer(new char [size]);
some_io_function(buffer.get(), size); // get() returnes raw pointer

不幸的是,它无法检索缓冲区的大小,因此您必须将其存储在变量中。如果它让你感到困惑,那么 std::vector会做的工作:

std::vector<char> buffer(size);
some_io_function(buffer.data(), buffer.size()); // data() returnes raw pointer

如果你想传递缓冲区,这取决于你是怎么做的。

考虑以下情况:缓冲区在某处填充,然后在其他地方处理,存储一段时间,然后在某处写入并销毁。碰巧你永远不需要代码中的两个位置来拥有缓冲区,你可以简单地 std::move它从一个地方到另一个地方。对于这个用例,std::unique_ptr将完美运行,并且可以防止您偶尔复制缓冲区(而使用 std::vector 您可以错误地复制它,不会出现错误或警告)。

相反,如果您需要代码中的多个位置来保存同一个缓冲区(可能同时在多个位置填充/使用/处理),您肯定需要 std::shared_ptr .不幸的是,它没有类似数组的特化,所以你必须传递适当的删除器:

std::shared_ptr<char> buffer(new char[size], std::default_delete<char[]>());

第三个选项是如果你真的需要复制缓冲区。然后,std::vector会更简单。但是,正如我已经提到的,我觉得这不是最好的方法。此外,您始终可以通过 std::unique_ptr 复制缓冲区保留。或 std::shared_ptr手动,清楚地记录您的意图:

std::uniqure_ptr<char[]> buffer_copy(new char[size]);
std::copy(buffer.get(), buffer.get() + size, buffer_copy.get());

关于c++ - 用于分配/释放 I/O 缓冲区的现代 C++ 习惯用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30594966/

有关c++ - 用于分配/释放 I/O 缓冲区的现代 C++ 习惯用法的更多相关文章

  1. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

    通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

  4. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  5. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

  6. ruby - inverse_of 是否适用于 has_many? - 2

    当我使用has_one时,它​​工作得很好,但在has_many上却不行。在这里您可以看到object_id不同,因为它运行了另一个SQL来再次获取它。ruby-1.9.2-p290:001>e=Employee.create(name:'rafael',active:false)ruby-1.9.2-p290:002>b=Badge.create(number:1,employee:e)ruby-1.9.2-p290:003>a=Address.create(street:"123MarketSt",city:"SanDiego",employee:e)ruby-1.9.2-p290

  7. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  8. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  9. ruby - 使对象的行为类似于 ruby​​ 中并行分配的数组 - 2

    假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje

  10. ruby - "undefined method"用于 rails 模型 - 2

    我正在使用带有Rails的Devise,我想添加一个方法“getAllComments”,所以我这样写:classUser在我的Controller中:defdashboard@user=current_user@comments=@user.getAllComments();end当我访问我的url时,我得到了undefinedmethod`getAllComments'for#我做错了什么?谢谢 最佳答案 因为getAllComments是一个类方法,而您正试图将其作为实例方法访问。您要么需要访问它:User.getAllCom

随机推荐