C++ 在使用std::string与C风格的API交互时,是否可以避免使用临时缓冲区?

C++ 在使用std::string与C风格的API交互时,是否可以避免使用临时缓冲区?,c++,c,C++,C,在回答这个问题之前,我应该说我认为答案可能是否定的,但我想看看其他人对这个问题的看法 我花费了大部分时间编写与Win32 API交互的C++,它与大多数C风格API一样,都希望: 拿着我提供的缓冲器,对它们进行操作 或者返回指向我以后需要释放的缓冲区的指针 这两种情况本质上都意味着,如果您想在代码中使用std::string,您必须接受这样一个事实,即每次从临时缓冲区构造std::string时,您都要进行大量的字符串复制 最好是: 能够允许C风格的API安全地直接变异std::string,并

在回答这个问题之前,我应该说我认为答案可能是否定的,但我想看看其他人对这个问题的看法

我花费了大部分时间编写与Win32 API交互的C++,它与大多数C风格API一样,都希望:
  • 拿着我提供的缓冲器,对它们进行操作
  • 或者返回指向我以后需要释放的缓冲区的指针 这两种情况本质上都意味着,如果您想在代码中使用
    std::string
    ,您必须接受这样一个事实,即每次从临时缓冲区构造
    std::string
    时,您都要进行大量的字符串复制

    最好是:

  • 能够允许C风格的API安全地直接变异
    std::string
    ,并预先保留其分配和设置其大小(以缓解场景1)
  • 能够在现有的
    char[]
    周围包装
    std::string
    (缓解场景2)

  • 有没有一种很好的方法来实现这两种功能,或者我应该接受在旧式API中使用
    std::string
    会带来固有的成本?场景1看起来特别棘手,因为
    std::string
    有一个短字符串优化,其缓冲区可以位于堆栈上,也可以位于堆上,具体取决于其大小。

    在C++11中,您只需将指针传递到字符串的第一个元素(
    &str[0]
    ):其元素保证是连续的

    以前,您可以使用
    .data()
    .c_str()
    ,但字符串不能通过这些更改



    否则,是的,您必须执行复制。但是我不会太担心这个问题,直到分析表明这确实是您的问题。

    您可以使用
    std::vector
    。您可以直接将指向第一个字符的指针传递到C代码中,并让C代码编写它,这是字符串无法做到的。你想在字符串上执行的许多操作也可以在
    std::vector上执行。

    我认为在std:(w)字符串上可以安全执行的唯一一件事是将其作为用户不会修改的输入传递;使用
    .c_str()
    获取指向
    (W)CHAR

    的指针。您可能只需将字符串的
    .data()
    强制转换为
    CHAR*
    ,它很可能会起作用。与所有优化一样,确保这段代码实际上是瓶颈。如果是,请将其封装在可内联的函数、模板类或其他东西中,以便您可以为其编写一些测试,并在某些平台上无法运行时更改其行为。

    @Tomalak因为问题涉及C/C++互操作?将
    std::vector
    .data()一起使用如何“访问”?/KORADAD:它同样适用于C++和C++之间的互不带字符串,他在C++中编写。我不认为C与此有多大关系。@KerrekSB
    data
    提供只读缓冲区,但不提供C样式的字符串(不一定以null结尾)
    c_str
    是一条路。@KonradRudolph:是的,你必须投入一些额外的工作,但至少你得到了一个有管理的、动态的、可变的数组。。。C API也会终止你的字符串,但不可变:(与以前版本C++中的代码> CyString()/代码>没有什么不同。为什么会被否决?当然可以写入<代码>和STR(0)< /CUL>或指针。<代码>操作符[]
    以常量和非常量的形式重载。
    reserve
    允许您按照其名称执行操作,
    resize
    允许您将长度截断为C API函数报告的随后写入的字符数。此外,分配的内存保证是连续的。为什么这不起作用?@Tomalak:a s轻度关注-
    str[str.size()]
    返回对0终止符的引用,但是否可以保证对于非空字符串,
    (&str[str.size()-1])+1
    指向0终止符?21.4.1/5处字符串的连续性要求文本(它说
    @Tomalak OCD对该终止符很强。;-)我不知道你们说的是什么,语法英语不是我的拿手好戏吗?;-)我确实用这种方法处理与字符串无关的缓冲区,而且效果很好。然而,对字符串使用这种方法有点糟糕,因为这样你就不能在缓冲区中使用任何字符串方法,而这会使使用它的意义无效。将近三年了,你从来没有读过编辑框上方的格式帮助?从未想过人们是如何获得这些代码部分的?对不起,是的,我很差劲:P(而且之前已经多次输入代码部分)我正在从手机输入回复,无法使其工作,也看不到帮助部分。另外,我应该是在工作:P,这不是借口,我同意。@Benj许多字符串函数可以用其他方式完成,例如使用std::find而不是find成员。但是,是的,在很多情况下,这不是一个好的解决方案。在C++03中,它可能是最好的一个,有时会想是的,我怀疑你是对的,但我希望有人能想出一个天才的解决方案;-)这可能是可行的,但从标准的角度来看,它肯定是不可移植的。Tomalak的解决方案是唯一合法的解决方案,但它只适用于C++11。如果可能的话,我肯定会避免这种情况,但我确实想知道-哪些平台不按顺序排列字符串?没有任何重要性。Herb Sutter在一次C++0x会议上报告了一次草率调查,他们讨论了将连续性要求添加到
    std::string
    ,没有人能想到一个实际在生产中使用的实现,它没有使用连续字符串。进行这项调查的原因是允许他们添加要求,而不必担心是否删除了任何选项