指向char vs String的指针

时间:2015-02-05 14:22:31

标签: c++ c

考虑这两段代码。他们将base10号码转换为baseN号码,其中N是给定字母表中的字符数。实际上,它们生成给定字母表的字母排列。假设1等于字母表的第一个字母。

#include <iostream>
#include <string>

typedef unsigned long long ull;
using namespace std;

void conv(ull num, const string alpha, string *word){
    int base=alpha.size();
    *word="";
    while (num) {
        *word+=alpha[(num-1)%base];
        num=(num-1)/base;
    }
}

int main(){
    ull nu;
    const string alpha="abcdef";
    string word;
    for (nu=1;nu<=10;++nu) {
        conv(nu,alpha,&word);
        cout << word << endl;
    }
    return 0;
}

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef unsigned long long ull;

void conv(ull num, const char* alpha, char *word){
    int base=strlen(alpha);
    while (num) {
        (*word++)=alpha[(num-1)%base];
        num=(num-1)/base;
    }
}

int main() {
    char *a=calloc(10,sizeof(char)); 
    const char *alpha="abcdef";
    ull h;
    for (h=1;h<=10;++h) {
        conv(h,alpha,a);
        printf("%s\n", a);
    }
}

输出相同:

  

     

B'/ P>      

C

     

d

     

AA

     

BA

     

CA

     

不,我没有忘记撤消字符串,因为代码澄清而取消了反转。

出于某种原因,速度对我来说非常重要。我已经测试了从上面的示例编译的可执行文件的速度,并注意到使用string编写的使用char *的c ++的速度比使用{{使用{C>编写的速度快 10倍。 1}}。

每个可执行文件都使用GCC的-O2标志进行编译。我使用更大的数字来运行测试来转换,例如1e8甚至更多。

问题是:在这种情况下,为什么string的速度低于char *

5 个答案:

答案 0 :(得分:3)

您的代码段与不是等效。 *a='n' 附加到char数组。它会将数组中的第一个char更改为'n'


在C ++中,std::string应该优先于char数组,因为它们更容易使用,例如只需使用+=运算符即可完成追加。

此外,他们会自动为char阵列无法管理他们的记忆。话虽这么说,std::string比手动管理的char数组更不容易出错。

答案 1 :(得分:1)

  

可以使用char *和string来处理C ++中的某些文本。在我看来,字符串添加比指针添加慢得多。为什么会这样?

这是因为当你使用char数组或处理指向它的指针(char *)时,内存只被分配一次。您用&#34;添加&#34;描述的内容只是指向数组的指针的迭代。所以它只是移动一个指针。

// Both allocate memory one time:
char test[4];
char* ptrTest = new char[4];
// This will just set the values which already exist in the array and will
// not append anything.
*(ptrTest++) = 't'
*(ptrTest++) = 'e';
*(ptrTest++) = 's';
*(ptrTest) = 't';

当您使用字符串时,+=运算符实际上字符附加到字符串的末尾。为了实现这一点,每次向字符串追加内容时,都会动态分配内存。这个过程确实需要比迭代指针更长的时间。

// This will allocate space for one character on every call of the += operator
std::string test;
test += 't';
test += 'e';
test += 's';
test += 't';

答案 2 :(得分:1)

跟踪你的代码:

*a='n';
// 'n0000'
//  ^
//  a
++a;
// 'n0000'
//   ^
//   a
*a='o'
// 'no000'
//   ^
//   a

最后,指向其原始地址+ 1,这是o。如果你打印一个,你会得到'o'。

无论如何,如果你需要'没什么'而不是'不'怎么办?它不适合5个字符,你需要重新分配mem等。这类事情是字符串类在幕后为你做的,而且速度足够快,所以它几乎不是每个场景都有问题。

答案 3 :(得分:0)

std::string a(2,' ');
a[0] = 'n';
a[1] = 'o';

在构造函数中更改字符串的大小,或使用您选择的reserve,resize方法。

你在问题​​中混合了不同的东西,一个是字节的原始表示,可以解释为字符串,没有语义或检查,另一个是带有检查的字符串的抽象,相信我,它是很多更重要的是安全性和避免可能导致代码注入和权限提升的段错误,而不是2ms。

答案 4 :(得分:0)

从std :: string文档(here)可以看出,

basic_string& operator+=(charT c)

相当于在该字符串上调用push_back(c),所以

string a;
a+='n';
a+='o';

相当于:

string a;
a.push_back('n');
a.push_back('o');

push_back确实比原始指针操作更多地处理,因此更慢。例如,它负责字符串类的自动内存管理。