c++ - 在 C++ 中,CPython 字符串连接的等价物是什么?

标签 c++ python

这个问题在这里已经有了答案:




8年前关闭。




Possible Duplicate:
Simple string concatenation



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

if i have a string x='wow' applying the function add in python :

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

how can i do that in C++?



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

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

我把原来的标题“select python or 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::stringstd::wstring ),例如引用 CPython 3k documentation :

    object.__add__(self, other)
    … to evaluate the expression x + y, where x is an instance of a class that has an __add__() method, x.__add__(y) is called.



    举个例子,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;
    }
    

    与给出的许多错误答案的主要区别
    the original question ,
    是 C++ 对应是一个表达式,而不是更新。

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

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

    添加了 CPython 2.4
    the following
    优化,仅适用于窄字符串:

    String concatenations in statements of the form s = s + "abc" and s += "abc" are now performed more efficiently in certain circumstances. This optimization won't be present in other Python implementations such as Jython, so you shouldn't rely on it; using the join() method of strings is still recommended when you want to efficiently glue a large number of strings together. (Contributed by Armin Rigo.)



    听起来可能不多,但在适用的情况下,此优化
    减少串联序列二次时间 O(n2)
    线性时间 O(n),在最终结果的长度 n 中。

    首先,优化用更新替换连接,例如仿佛
    x = x + a
    x = x + b
    x = x + c
    

    或者就此而言
    x = x + a + b + c
    

    被替换为
    x += a
    x += b
    x += c
    

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

    此时x持有对该对象的唯一引用。这意味着
    对象可以通过附加 b 的更新分配来更新,因为有
    没有观察者。同样对于 c 的附加.

    这有点像量子力学:你无法观察这个肮脏的东西
    一直在进行,并且在任何人都有可能观察到的情况下从未完成
    阴谋,但你可以通过统计数据推断它一定是在进行的
    您收集有关性能的信息,因为线性时间与二次时间完全不同!

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

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

    为了在 C++ 中忠实地重现 CPython 代码片段,
  • 应该捕获操作的最终结果和表达式性质,
  • 并且还应该捕捉它的性能特征!

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

    对于 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.
    }
    

    关于c++ - 在 C++ 中,CPython 字符串连接的等价物是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13021985/

    相关文章:

    python - pip install MySQL-python 返回找不到vcvarsall.bat

    python - str.replace() 的时间复杂度是 O(n^2) 吗?

    python - 列表:查找第一个索引并计算列表列表中特定列表的出现次数

    python - GAE 应用程序的基于角色的授权机制

    python - Pyodbc-如果表存在则不要在 SSMS 中创建

    c# - 将字节数组作为 char* 从 C# 传递到 C++ DLL

    c++ - 为什么包含 std::stringstream 的类的 move 语义会导致编译器错误?

    c++ - Qt WebEngine 打印时不正确的页边距

    c++ - 如何绘制自定义形状的元素?

    c++ - 如何使用 fread 和缓冲从 C++ 中的文件中读取文件?