【问题标题】:Does std::move on std::string garantee that .c_str() returns same result?std::move on std::string 是否保证 .c_str() 返回相同的结果?
【发布时间】:2022-10-27 07:45:11
【问题描述】:

我想提供零拷贝、基于移动的 API。我想将一个字符串从线程 A 移动到线程 B。从意识形态上讲,似乎 move 应该能够简单地将数据从实例 A 传递\移动到新实例 B,而复制操作最少甚至没有(主要用于地址)。所以像数据指针这样的所有数据都将被简单地复制而不是新的实例(通过移动构造)。那么 std::move on std::string 是否保证 .c_str() 在移动之前的实例和通过移动构造函数创建的实例返回相同的结果?

【问题讨论】:

  • std::move 只是演员。它没有任何事物。
  • 我不相信后续调用 .c_str() 一定会返回相同的指针即使没有尝试的举动。标准要求(即使是隐含的要求)将是一件奇怪的事情,尽管我希望语言律师引用我的标准。 (我知道它必须是真奇怪虽然这样做的实现)
  • @MikeVine 显然不能期望在更改之间返回相同的指针。例如,如果字符串大小被任意增加。如果标准中对此没有任何说明,那么任何非常量方法都可以自由影响它。
  • @Johan Lundberg 甚至都不是。我可以想到一个字符串实现(比如说一个将字符串存储两次的实现,我知道这很愚蠢,但我认为它符合标准)如果调用两次而不进行修改,它可以从 c_str() 返回一个不同的指针。至少我认为这没问题,但就像我说的那样,我希望看到标准中不允许这样做的内容。纯粹是为了兴趣。
  • C++ 标准库类和函数是线程安全的,因为它们允许在没有外部同步的情况下访问常量方法。 Const 方法被允许改变内部状态(可变的或丢弃 const),只有当它可以通过仍然保持正确的行为(原子或以其他方式同步,如果必须)或 as-if 来完成时。 herbsutter.com/2013/01/01/video-you-dont-know-const-and-mutable

标签: c++ c++11 move move-semantics


【解决方案1】:

不。不要求 std::string 使用动态分配或对此类分配执行任何特定操作(如果有的话)。事实上,现代实现通常将短字符串放入字符串对象本身并且不分配任何东西;那么移动就和复制一样了。

重要的是要记住 std::string不是一个容器,尽管它看起来非常相似。与 std::string 相比,容器对其元素提供了更强的保证。

【讨论】:

  • 因此,例如在 std::vector 的情况下,我们保证指针指向移动后指向同一位置的第一个点?
  • @DuckQueen:我不太确定。标准说移动后的目标容器与移动前的操作数具有相同的值,但这有点含糊。只有 swap 才说没有容器元素被触及。
【解决方案2】:

不,这不能保证。

保证它基本上会禁止(例如)短字符串优化,其中短字符串的整个主体存储在字符串对象本身中,而不是在堆上单独分配。

至少就目前而言,我认为 SSO 被认为足够重要,以至于委员会极不愿意禁止它(但这可能会改变——当最初的 C++98 标准被编写时,他们费了很大的劲才允许复制——写入字符串,但现在禁止使用)。

【讨论】:

    【解决方案3】:

    不,

    但如果需要,一个选项是将字符串放入std::unique_ptr。就我个人而言,我通常不会将 c_str() 值依赖于本地范围之外的其他内容。

    示例,根据要求:

    #include <iostream>
    #include <string>
    #include <memory>
    
    int main() {
        std::string ss("hello");
        auto u_str = std::make_unique<std::string>(ss);
        std::cout << u_str->c_str() <<std::endl;
        std::cout << *u_str <<std::endl;
        return 0;
    }
    

    如果您没有 make_unique(C++14 中的新功能)。

    auto u_str = std::unique_ptr<std::string>(new std::string(ss));
    

    或者只是从 proposal by S.T.L.: 复制整个实现

    Ideone example on how to do that

    【讨论】:

    • 如何将字符串放入 unique_ptr.having 中?
    【解决方案4】:

    它是 documented here,因此您可以假设 c_str() 结果在某些条件下是稳定的。

    但是,您不能假设 c_str() 在移动后将保持不变。 在实践中,它会在长字符串的情况下保留,但不会在短字符串的情况下保留。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-30
      • 2013-04-05
      • 2011-09-21
      • 2017-10-19
      相关资源
      最近更新 更多