Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::string应该由函数的值返回还是由“返回”;std::string&;s";作为论据?_C++_String_Performance_C++11 - Fatal编程技术网

C++ std::string应该由函数的值返回还是由“返回”;std::string&;s";作为论据?

C++ std::string应该由函数的值返回还是由“返回”;std::string&;s";作为论据?,c++,string,performance,c++11,C++,String,Performance,C++11,对于从函数中返回字符串,这两种方法中哪一种更有效(即我应该使用哪一种): 或 我知道答案可能取决于特定的编译器。但是我想知道在现代C++代码中推荐的方法(如果有一个方法)。 根据下面的“轨道上的轻量级比赛”评论,以下是我在问这个问题之前在stackoverflow上发现的一些相关问题: 这些都没有回答我关于从函数返回值与将字符串作为额外参数返回的特殊问题。对于返回新创建的字符串,我肯定会采用按值返回的方法。按值返回对象的典型编译器实现是让编译器在调用函数中为对象分配空间,并向其传递指向该

对于从函数中返回字符串,这两种方法中哪一种更有效(即我应该使用哪一种):

我知道答案可能取决于特定的编译器。但是我想知道在现代C++代码中推荐的方法(如果有一个方法)。 根据下面的“轨道上的轻量级比赛”评论,以下是我在问这个问题之前在stackoverflow上发现的一些相关问题:


这些都没有回答我关于从函数返回值与将字符串作为额外参数返回的特殊问题。

对于返回新创建的字符串,我肯定会采用按值返回的方法。按值返回对象的典型编译器实现是让编译器在调用函数中为对象分配空间,并向其传递指向该分配空间的指针,该指针与引用参数基本相同,但有一个重要的区别:passbyreference输出参数需要将对完全构造的字符串的引用传递到被结果覆盖的函数中,而在按值返回的情况下,函数本身构造对象


请注意,有一个特定的用例中,通过引用传递解决方案的速度更快:如果调用方反复调用此函数以更改同一变量,则函数内部的覆盖正是所需的,而在调用方中返回和赋值将导致结果在一个临时的分配给调用者端的变量。如果使用C++11之前的编译器,它甚至会被分配副本。

对于返回新创建的字符串,我肯定会使用按值返回的方法。按值返回对象的典型编译器实现是让编译器在调用函数中为对象分配空间,并向其传递指向该分配空间的指针,该指针与引用参数基本相同,但有一个重要的区别:passbyreference输出参数需要将对完全构造的字符串的引用传递到被结果覆盖的函数中,而在按值返回的情况下,函数本身构造对象


请注意,有一个特定的用例中,通过引用传递解决方案的速度更快:如果调用方反复调用此函数以更改同一变量,则函数内部的覆盖正是所需的,而在调用方中返回和赋值将导致结果在一个临时的分配给调用者端的变量。如果您使用C++11之前的编译器,它甚至会被分配副本。

让我对第二个版本的
f()
进行微优化,并将其命名为
g()

在每次迭代中,都有一个内存分配。分配的总数将是迭代次数+1,在本例中为11

输出参数法:

int main(int argc, char* argv[]) {

    string s(argv[1]);

    for (int i=0; i<10; ++i) {

      string temp = f(s); // at least 1 memory allocation in each iteration, ouch!

      fprintf(stderr, "%s\n", temp.c_str());
    }
}
int main(int argc, char* argv[]) {

    string s(argv[1]);

    string temp; // note that this time, it is outside the loop

    for (int i=0; i<10; ++i) {

      g(s, temp);

      fprintf(stderr, "%s\n", temp.c_str());
    }
}
intmain(intargc,char*argv[]){
字符串s(argv[1]);
string temp;//注意,这一次,它在循环之外

对于(int i=0;i让我对第二个版本的
f()
进行微优化,并将其称为
g()

在每个迭代中,都有一个内存分配。分配的总数将是迭代次数+1,在本例中为11

输出参数法:

int main(int argc, char* argv[]) {

    string s(argv[1]);

    for (int i=0; i<10; ++i) {

      string temp = f(s); // at least 1 memory allocation in each iteration, ouch!

      fprintf(stderr, "%s\n", temp.c_str());
    }
}
int main(int argc, char* argv[]) {

    string s(argv[1]);

    string temp; // note that this time, it is outside the loop

    for (int i=0; i<10; ++i) {

      g(s, temp);

      fprintf(stderr, "%s\n", temp.c_str());
    }
}
intmain(intargc,char*argv[]){
字符串s(argv[1]);
string temp;//注意,这一次,它在循环之外

对于(int i=0;i第一种选择,
返回s+“一些文本”
,更简单。它在内存分配方面的行为也很简单:first
s+计算某些文本
,可能导致分配一个新的
字符串
对象,该对象具有足够的容量来保存结果。该对象是返回值,假设复制省略,否则会发生移动

正如Ali所指出的,第二个接口为用户提供了在多次调用中重用字符串缓冲区的机会。利用该功能需要更多的代码,并且会带来更多的复杂性

此外,根据他的测量结果,很难判断哪一方最终获胜。幸运的是,有一条中间路线:

#if STRING_BUFFER_REUSE_OPTIMIZATION

string h( string const & s, string && result = {} ) {
    result.clear();
    result += s;
    result += "some text";
    return std::move( result );
}

#else

string const no_hint = {};

string h( string const & s, string const & hint = no_hint ) {
    return s + "some text";
}

#endif

有了它,您可以根据每个构建目标上的当前测量值设置
字符串\u缓冲区\u重用\u优化
宏。两种内存访问样式都适用于相同的接口,没有任何牺牲。

第一种选择,
返回s+“一些文本”;
,则更简单。它在内存分配方面的行为也很简单:首先计算
s+”一些文本
,可能会导致分配一个新的
字符串
对象,该对象具有足够的容量来保存结果。该对象是返回值,假设复制省略,否则会发生移动

正如Ali所指出的,第二个接口为用户提供了在多次调用中重用字符串缓冲区的机会。利用该功能需要更多的代码,并且会带来更多的复杂性

此外,根据他的测量结果,很难判断哪一方最终获胜。幸运的是,有一条中间路线:

#if STRING_BUFFER_REUSE_OPTIMIZATION

string h( string const & s, string && result = {} ) {
    result.clear();
    result += s;
    result += "some text";
    return std::move( result );
}

#else

string const no_hint = {};

string h( string const & s, string const & hint = no_hint ) {
    return s + "some text";
}

#endif

有了它,您可以根据每个构建目标上的当前测量值设置
STRING\u BUFFER\u REUSE\u OPTIMIZATION
宏。两种内存访问样式都适用于相同的接口,没有任何牺牲。

C++11按值返回,因为如果没有省略,则移动了
按值返回std::STRING作为参数的含义是什么?@LightnessRacesinOrbit是的,这个问题的措辞有点不幸,但这是一个有趣的问题!请阅读我的答案。@Ali你的观点是正确的,但你至少应该对“过早选择”加上点头