C++ 将字符串分配给字符串返回类型函数而不复制

C++ 将字符串分配给字符串返回类型函数而不复制,c++,qt,move,C++,Qt,Move,我想学习如何高效地写作(谁不这么做),我想让我的例子包含熟悉和简单的概念。我实际上在使用Qt,但我希望这不是一个问题,因为这个问题相当普遍。我有一个函数是这样的: QString elide(const QString& text, int length) { if (text.length() < length) return text; QString elided = text.mid(0, length); elided.

我想学习如何高效地写作(谁不这么做),我想让我的例子包含熟悉和简单的概念。我实际上在使用Qt,但我希望这不是一个问题,因为这个问题相当普遍。我有一个函数是这样的:

QString elide(const QString& text, int length)
{
    if (text.length() < length) 
        return text;
    
    QString elided = text.mid(0, length);
    elided.append("...");

    qDebug() << &elided[0];

    return elided;
}
QString-elide(常量QString&text,int-length)
{
if(text.length()过敏,50);
在elide函数中,复制仍然存在


编辑:显然,我想了解移动语义,但即使在这个简单的示例中,我在实现它们时也遇到了困难。我知道如果省略复制,可能的性能增益可以忽略不计,但这里的问题是原则问题,以及如何工作。

C++不能保证以这种方式省略复制e> elide()
使用
返回
。可以更详细地讨论这一点,但很明显,这将是无关紧要的。还有另一个更基本的问题。底线是,您不能保证从
elide()返回时会删除隐式副本,这里

最近的C++标准允许编译器在这里强> >可选/<强> ELID,但即使调用函数中发生了什么:

,这也没有真正帮助您。
allergies = elide(patient->allergies, 50);
这是将返回值从
elide()
分配给另一个对象。简而言之,这使得某种类型的副本不可避免。它可能不会最终成为实际副本(这将调用对象的赋值操作符).但是这里发生了某种复制,不管怎样。就像太阳每天从东方升起一样确定(除了两极附近)

另一方面,如果返回值用于构造新对象,例如:

auto allergies = elide(patient->allergies, 50);
现在有可能(但不能保证)如果编译器在
从函数返回值时省略隐式复制,则不会发生复制,并且在
elide()
内部,这个对象被有效地构造在“适当的位置”,就在
allergies
所在的位置


但是您正在将返回的值分配给一个现有的对象。这使世界变得完全不同。在
elide()中构造的对象
必须是一个不同的对象,原因很明显。因此,出于根本原因,无法删除此副本。

C++不保证以
elide()的方式删除副本
使用
return
。可以更详细地讨论这一点,但很明显,这将是不相关的。还有另一个更基本的问题。底线是,您不能保证从
elide()返回会删除隐式副本,这里

最近的C++标准允许编译器在这里强> >可选/<强> ELID,但即使调用函数中发生了什么:

,这也没有真正帮助您。
allergies = elide(patient->allergies, 50);
这是将返回值从
elide()
分配给另一个对象。简而言之,这使得某种类型的副本不可避免。它可能不会最终成为实际副本(这将调用对象的赋值操作符).但是这里发生了某种复制,不管怎样。就像太阳每天从东方升起一样确定(除了两极附近)

另一方面,如果返回值用于构造新对象,例如:

auto allergies = elide(patient->allergies, 50);
现在有可能(但不能保证)如果编译器在
从函数返回值时省略隐式复制,则不会发生复制,并且在
elide()
内部,这个对象被有效地构造在“适当的位置”,就在
allergies
所在的位置


但是您正在将返回的值分配给一个现有的对象。这使世界变得完全不同。在
elide()中构造的对象
必须是一个不同的对象,原因很明显。因此,出于根本原因,无法删除此副本。

请避免指出您是某项技术的新手,因为它与您的问题无关。在这里,我们不只关注问题,而不关注OP。OP的特征应该不要也不能干涉你的回答方式,因为如果你是专家或初学者,答案将是相同的。写作课上不是抄袭吗?请避免指出你对某项技术是新手,因为它与你的问题无关。在这里,我们不只关注问题,而不关注OP。OP的特点是ld不会也不能干预您的回答方式,因为如果您是专家或初学者,答案将是相同的。QString不是一个编写类的副本吗?这没有提到
allergies=elide(patient->allergies,50);
将调用移动分配操作符(
QString
有一个),因为
elide(patient->allergies,50)
是一个prvalue。我不知道如何实现
QString
,但这可能比字符串复制快得多,因为只需要修改几个指针/整数,而不需要复制整个字符串内容。仍然可以复制一个副本(省略不保证),但编译器可以对此进行优化,使其成为(1) ,据我所知。这并没有提到
allergies=elide(patient->allergies,50);
将调用移动分配操作符(
QString
有一个),因为
elide(patient->allergies,50)
是一个PR值。我不知道如何调用