3

以下面的函数为例

string print()
{
   return (some string that has been formed);
};

现在让我们说这个打印函数将形成一个非常大的字符串,需要返回到从另一个类调用它的函数。

现在说这个打印函数可能会被调用数千次。有没有正确和更快的方法来做到这一点?

在 Visual Studio 中,您可以执行此操作

void print(string& lines)
{
   lines = (some string that has been formed);
};

但是 g++ 不会编译它,也不应该这样做,因为这可能是一个临时对象,随时可能消失。所以据我了解,我可以做到这一点

void print(const string& lines)
{
};

如果我只想在不修改它的情况下检索该字符串中的某些内容并快速完成。但我确实想修改它。所以这个我做不到。

这导致我的问题是声明一个指向对象的新指针将是最快的方法?还是更慢?还是只是不值得。即(不确定这是否可行?)

void print(string* lines)
{
   string formedString; // the string that has been formed
   lines = formedString&;
};

最后,如果我在运行时加载对象,并通过以下方式将它们添加到树中:

void add(const ItemType& item)
{
   someNode->item = item;
};

item最初是在调用 this 的函数范围内临时存储的对象,add()那么将它分配给节点会导致调用函数的堆栈停留更长时间吗?或者这样可以吗?我以后也可以编辑item,还是现在卡在 const 上?

只是学习思维的问题:)

4

2 回答 2

8

只需返回字符串并完成它。

编译器将使用返回值优化(或命名的返回值优化)来消除返回字符串时的额外副本。一个真正新的编译器还将有一个移动构造函数和移动赋值运算符 for std::string,这将为完成同样的事情提供更大的保证。

编辑(对不起,我最初错过了最后一个问题):在该函数返回后,分配一个值不会保留该函数的任何本地内容。当一个函数返回时,它的所有局部变量都将被销毁。如果您将该函数的分配给在它返回后持续存在的东西,那没问题——它将被复制(或可能移动)到目的地。如果您保留对该本地的指针或引用,则在函数返回后它将悬空,因此尝试使用引用或取消引用该指针将导致 UB。

根据情况,后者可能是您想要使用 a 的情况,因此函数和外部代码都将共享对数据的访问权限,并且只有在对数据的两个引用shared_ptr都被销毁时,数据才会被销毁。

于 2013-03-28T02:31:21.573 回答
2

在 C++11 或具有基本 C++11 特性的编译器中,答案是:

想要速度?通过值传递,对象支持移动语义。

你的string类型(无论是 astd::string还是你有什么)应该支持快速移动语义。

如果从函数返回局部变量,在 C++11 下,它将被隐式移动到返回值中。如果您的函数主体从调用者站点可见,并且您有一个变量是函数的返回值,则 NRVO 可能会发生,导致不会发生复制或移动(而是实际构造的对象最终位于呼叫站点)。

每当您最终想要复制传入的参数时,同样在参数中使用按值传递。这可以允许调用者在一些上下文中执行传递移动,并且调用者可以std::move在非自动上下文中显式地提供非常好的性能。

如果您不制作副本,请通过const string&,它可以绑定到临时文件。

如果您正在修改数据,请通过string& 通过string,然后将新字符串作为返回值的一部分返回。通过快速移动构造,在最坏的情况下,第二个几乎与第一个一样快,并且在某些情况下可能更快(理论上,在第二种情况下,NRVO 的多重链接是可能的!)

于 2013-03-28T02:31:29.897 回答