在 C++ 中,CPython 字符串连接的等效项是什么? [复制]

2023-11-24

可能的重复:
简单的字符串连接

昨天,当我写这篇文章时,有人问SO

如果我有一个字符串x='wow'应用函数add在Python中:

x='wow'
x.add(x)
'wowwow'

我怎样才能在 C++ 中做到这一点?

With add(这是不存在的)更正为__add__(一个标准 方法)这是一个深刻而有趣的问题,涉及微妙的低 级别细节、高级算法复杂性考虑因素,以及 甚至是线程!,但它的表述方式非常简短。

我正在转发原来的问题作为我自己的,因为我没有机会提供正确的 在删除之前回答,并且我努力恢复原来​​的问题,所以 我认为我可以帮助增加对这些问题的总体了解,但失败了。

我把原来的标题“选择python还是C++”改成了……

  • 在 C++ 中,CPython 字符串连接的等效项是什么?

从而稍微缩小问题范围。


代码片段的一般含义。

给定的代码片段

x = 'wow'
x.__add__( x )

在 Python 2.x 和 Python 3.x 中具有不同的含义。

在 Python 2.x 中,字符串是默认的窄弦,每个编码单元一个字节, 对应于C++char基于字符串。

在 Python 3.x 中,字符串是宽弦,保证代表 Unicode, 对应于C++的实际使用wchar_t基于字符串,同样具有未指定的 2 或 4 字节 每个编码单元。

不考虑效率__add__方法在两个 main 中的行为相同 Python版本,对应C+++运算符为std::basic_string(即,对于std::string and std::wstring),例如引用CPython 3k 文档:

object.__add__(self, other)
... 评估表达式x + y, where x是一个类的实例,该类具有__add__()方法,x.__add__(y)叫做。

举个例子,CPython 2.7 代码

x = 'wow'
y = x.__add__( x )
print y

通常会写成

x = 'wow'
y = x + x
print y

对应于以下 C++ 代码:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    auto const x = string( "wow" );
    auto const y = x + x;
    cout << y << endl;
}

与给出的许多错误答案的主要区别原来的问题, C++对应的是表达,而不是一个update.

也许很自然地认为方法名称__add__意味着改变 字符串对象的值的更新,但相对于可观察的 Python 字符串的行为是不可变字符串。他们的价值观永远不会改变,因为 在Python代码中可以直接观察到。这与 Java 中的相同 C#,但与 C++ 的可变特性非常不同std::basic_string字符串。

CPython 中的二次到线性时间优化。

添加了 CPython 2.4下列优化,对于窄弦 only:

形式语句中的字符串连接s = s + "abc" and s += "abc"现在在某些情况下执行效率更高。本次优化 不会出现在其他 Python 实现中,例如 Jython,因此您不应该 依靠它;使用join()当您 想要有效地将大量字符串粘合在一起。 (阿明·里戈供稿。)

It may not sound like much, but where it’s applicable this optimization reduces a sequence of concatenations from quadratic time O(n2) to linear time O(n), in the length n of the final result.

首先,优化用更新代替串联,例如仿佛

x = x + a
x = x + b
x = x + c

或者就此而言

x = x + a + b + c

被替换为

x += a
x += b
x += c

在一般情况下,会有很多对字符串对象的引用x指的是,并且由于Python字符串对象必须看起来是不可变的,所以第一个 更新赋值无法更改该字符串对象。因此,一般来说,它具有 创建一个全新的字符串对象,并将其(引用)分配给x.

在此刻x holds the only对该对象的引用。这意味着 对象可以是updated通过附加的更新分配b,因为有 没有观察员。同样对于附加c.

这有点像量子力学:你无法观察这个肮脏的东西 继续进行,并且当有可能有人观察时它永远不会完成 阴谋,但你可以infer从统计数据来看,这一定是在发生 您收集有关性能的信息,因为线性时间与二次时间有很大不同!

线性时间是如何实现的?嗯,跟更新buffer的策略一样 与 C++ 中一样加倍std::basic_string可以做到,这意味着 现有的缓冲区内容只需要在每次缓冲区重新分配时复制, 而不是针对每个追加操作。这意味着总成本复制的最坏情况是最终字符串大小呈线性, 与总和相同(表示每次缓冲区加倍时的复制成本) 1 + 2 + 4 + 8 + … + N 小于 2*N。

C++ 中的线性时间字符串连接表达式。

为了在 C++ 中忠实地重现 CPython 代码片段,

  • 应捕获操作的最终结果和表达式性质,

  • 还应该捕捉其性能特征!

CPython 的直接翻译__add__ to C++ std::basic_string +失败 可靠地捕获 CPython 线性时间。 C+++字符串连接may由编译器以与 CPython 相同的方式进行优化 优化。或者不是——这意味着有人告诉初学者 C++ 相当于 Python 线性时间运算,是二次函数 时间 – 嘿,这就是你应该使用的......

对于C++的性能特点+=是基本答案,但是,这确实 无法捕捉Python代码的表达本质。

自然的答案是线性时间 C++字符串生成器翻译类 一系列的串联表达式+=更新,以便Python代码

from __future__ import print_function

def foo( s ):
    print( s )

a = 'alpha'
b = 'beta'
c = 'charlie'
foo( a + b + c )    # Expr-like linear time string building.

大致对应

#include <string>
#include <sstream>

namespace my {
    using std::string;
    using std::ostringstream;

    template< class Type >
    string stringFrom( Type const& v )
    {
        ostringstream stream;
        stream << v;
        return stream.str();
    }

    class StringBuilder
    {
    private:
        string      s_;

        template< class Type >
        static string fastStringFrom( Type const& v )
        {
            return stringFrom( v );
        }

        static string const& fastStringFrom( string const& s )
        { return s; }

        static char const* fastStringFrom( char const* const s )
        { return s; }

    public:
        template< class Type >
        StringBuilder& operator<<( Type const& v )
        {
            s_ += fastStringFrom( v );
            return *this;
        }

        string const& str() const { return s_; }
        char const* cStr() const { return s_.c_str(); }

        operator string const& () const { return str(); }
        operator char const* () const { return cStr(); }
    };
}  // namespace my

#include <iostream>
using namespace std;
typedef my::StringBuilder S;

void foo( string const& s )
{
    cout << s << endl;
}

int main()
{
    string const    a   = "alpha";
    string const    b   = "beta";
    string const    c   = "charlie";

    foo( S() << a << b << c );      // Expr-like linear time string building.
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C++ 中,CPython 字符串连接的等效项是什么? [复制] 的相关文章

  • HttpClient 像浏览器一样请求

    当我通过 HttpClient 类调用网站 www livescore com 时 我总是收到错误 500 可能服务器阻止了来自 HttpClient 的请求 1 还有其他方法可以从网页获取html吗 2 如何设置标题来获取html内容 当
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • Django 在选择列表更改时创建毫无意义的迁移

    我正在尝试使用可调用创建一个带有选择字段的模型 以便 Django 在选择列表更改时不会创建迁移 如中所述this https stackoverflow com questions 31788450 stop django from cr
  • 使用 LINQ 查找列表中特定类型的第一个元素

    使用 LINQ 和 C 在元素列表中查找特定类型的第一个项目的最短表示法是什么 var first yourCollection OfType
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • conda-env list / conda info --envs 如何查找环境?

    我一直在尝试 anaconda miniconda 因为我的用户使用随 miniconda 安装的结构生物学程序 并且作者都没有 A 考虑到可能存在其他 miniconda 应用程序 B 他们的程序将在多用户环境中使用 因此 使用 Arch
  • 如何有效地从 loadmat 函数生成的嵌套 numpy 数组中提取值?

    python中是否有更有效的方法从嵌套的python列表中提取数据 例如A array array 12000000 dtype object 我一直在使用A 0 0 0 0 当你有很多像 A 这样的数据时 这似乎不是一个有效的方法 我也用
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • Airflow Python 单元测试?

    我想为我们的 DAG 添加一些单元测试 但找不到任何单元测试 有 DAG 单元测试框架吗 有一个端到端的测试框架存在 但我猜它已经死了 https issues apache org jira browse AIRFLOW 79 https
  • 如何在与应用程序初始化文件不同的文件中迭代 api 路由

    我有一个 apiroutes py 文件 其中定义了许多路由 例如 api route api read methods GET api route api write methods POST 其中 api 是导入 from import
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • Python组合目录中的所有csv文件并按日期时间排序

    我有 2 年的每日数据分成每月文件 我想将所有这些数据合并到一个按日期和时间排序的文件中 我正在使用的代码组合了所有文件 但不按顺序 我正在使用的代码 import pandas as pd import glob os import cs
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • 为什么我们应该在 def __init__(self, n) -> None: 中使用 -> ?

    我们为什么要使用 gt in def init self n gt None 我读了以下摘录来自 PEP 484 https www python org dev peps pep 0484 the meaning of annotatio
  • 如何在sphinx中启用数学?

    我在用sphinx http sphinx pocoo org index html与pngmath http sphinx pocoo org ext math html module sphinx ext pngmath扩展来记录我的代
  • 如何禁止 celery 中的 pickle 序列化

    Celery 默认使用 pickle 作为任务的序列化方法 如中所述FAQ http ask github com celery faq html isn t using pickle a security concern 这代表一个安全漏
  • 在 Python 模块中使用 InstaLoader

    我正在尝试使用 Instaloader 下载与主题标签相关的照片以进行图像分析 我在GitHub存储库中找到了一个全面的方法 如何在终端中执行它 但是 我需要将脚本集成到Python笔记本中 这是脚本 instaloader no vide
  • Django South - 将 null=True 字段转换为 null=False 字段

    我的问题是 转变的最佳做法是什么null True场变成null False使用 Django South 的字段 具体来说 我正在与ForeignKey 你应该先写一个数据迁移 http south aeracode org docs t

随机推荐

  • 替换单列值

    如何替换数据框单列中的值 例如 dataz 列中的所有 0 值均变为 1 datay dataz 1 0 100 2 2 101 3 3 102 4 4 103 5 10 0 6 11 0 7 0 0 8 0 0 9 0 0 10 12 1
  • 检查函数参数的最佳方法? [关闭]

    Closed 这个问题是基于意见的 目前不接受答案 Locked 这个问题及其答案是locked因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动 我正在寻找一种有效的方法来检查 Python 函数的变量 例如 我想检查参数类
  • TaskCancellationException 如何避免成功控制流上的异常?

    在我们的应用程序中 我们大量使用异步 等待和任务 因此 它确实大量使用 Task Run 有时使用内置的取消支持CancellationToken public Task DoSomethingAsync CancellationToken
  • 使用二叉索引树进行 RMQ 扩展

    The RMQ问题可以这样扩展 给定的是一个数组n整数A 查询 x y 给定两个整数 1 x y n 找到最小值A x A x 1 A y 更新 x v 给定一个整数v且 1 x n do A x v 这个问题可以解决O log n 对于这
  • 当我为 Android RatingBar 使用自定义星星时,对于低于 0.5 的小数值始终显示半星

    我查了很多帖子 例如Android RatingBar更改星星颜色 更改评级栏中星星的颜色 其中评级栏是在android中动态创建的 如何设置评分栏的星星颜色 以更改评级栏中星星的颜色 我关注了这些帖子 并且能够更改自定义评级栏的星星 但在
  • HTML5 视频上一个 - 下一个和自动播放

    我是这个网站的新手 也是 HTML5 和 Javascript 的新手 并不是说我是初学者 当我看到它时 我有点了解 HTML5 和 Javascript 只是我自己无法正确编写它 我有很多视频 都是 mp4 大小相同 都在服务器上的同一个
  • 我应该如何使用区域获取 aws 区域名称

    您好 我想使用区域手段获取亚马逊网络服务 aws 区域名称 region is us east 1 region name is US East N Virginia region is us west 2 region name is U
  • Spring-Data-Elasticsearch 在底层使用什么 Elasticsearch 客户端?

    我想在我的项目中使用 Spring Data Elasticsearch 我看到了这个 The well known TransportClient is deprecated as of Elasticsearch 7 0 0 and i
  • 新 Ember 路由器的访问实例

    如何访问新 Ember 路由器的实例 API 文档似乎是指旧路由器或不正确 http emberjs com api classes Ember Router html RouterV2 不容易通过全局常量访问 这使得以 错误 方式做事变得
  • 使用 Base64UrlEncode 语句[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 目前不接受答案 我正在尝试通过代码发送电子邮件 但遇到了障碍 我当时正在工作this当 Base64UrlEncode 显示为红色时 我的代码中有相同的 using 语句 using Sys
  • 电话号码国家代码列表[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 Locked 这个问题及其答案是locked因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动 On this 维基百科条目我发现国际
  • 回形针附件文件大小

    如何获取回形针附件每种样式的文件大小 user attachment file size似乎不起作用 user attachment style size 给出与实际文件大小无关的数字 我没有找到如何获取文件大小对于给定的风格 除了原来的
  • 在boost中定义斐波那契堆的比较函数

    我需要在我的项目中使用斐波那契堆 并且我正在尝试从 boost 库使用它 但我无法弄清楚如何为任意数据类型设置用户定义的比较函数 我需要为结构节点构造一个最小堆 定义如下 struct node int id int weight stru
  • 标识符为“”的应用程序 ID 不可用。请输入不同的字符串

    我正在尝试添加新的 APP ID 来准备 App Store 提交 但在我提供的捆绑包 ID 下出现以下错误 带有标识符的应用程序 ID com domainName AppName 不可用 请输入不同的字符串 这是什么意思 我正在尝试添加
  • Apache Beam 云数据流流卡住侧输入

    我目前正在 GCP Dataflow 中构建 PoC Apache Beam 管道 在本例中 我想使用来自 PubSub 的主输入和来自 BigQuery 的侧输入创建流式传输管道 并将处理后的数据存储回 BigQuery 侧管线代码 si
  • 运行 jenkins 给出“包 org.junit 不存在”

    任何人都可以帮我解决这个错误吗 build project echo AntProject root jenkins jobs Ant workspace build xml javac Compiling 2 source files t
  • Python 的 super()、抽象基类和 NotImplementedError

    抽象基类在 Python 中仍然很方便 在编写一个抽象基类时 我希望每个子类都有一个spam 方法 我想写这样的东西 class Abstract object def spam self raise NotImplementedError
  • jqgrid 客户端排序与服务器端分页 - 数据消失

    它在 jqgrid 文档中指出 下面的代码应该允许使用服务器端分页进行本地排序 分页时网格数据消失 这个问题之前已经被问过 没有明确的答案 建议使用 loadonce true 意味着分页已关闭 我需要分页 稍后编辑以显示完整的 html
  • 无法将视图添加到 ASP.NET MVC 5 项目

    我正在尝试向 Visual Studio 2013 中的 ASP NET MVC 5 项目添加视图 但 添加 按钮呈灰色 Visual Studio 的默认安装缺少一些必需的元素 当我选择ASP NET和Web开发时 页面右侧没有选择以下选
  • 在 C++ 中,CPython 字符串连接的等效项是什么? [复制]

    这个问题在这里已经有答案了 可能的重复 简单的字符串连接 昨天 当我写这篇文章时 有人问SO 如果我有一个字符串x wow 应用函数add在Python中 x wow x add x wowwow 我怎样才能在 C 中做到这一点 With