抱歉,这个漫长的问题,但我试图尽可能清楚。这以某种方式遵循了我以前的问题 C ++中的字符串. 。我试图弄清楚如何在没有冗余内存分配的情况下从函数返回std ::字符串, 不依靠NRVO. 。我不想依靠NRVO的原因是:

  • 我们目前使用的编译器不支持它
  • 即使支持它,它可能并不总是在调试模式下启用
  • 在某些情况下可能会失败(例子)

请注意,我需要一个c ++ 03兼容解决方案(不幸的是,没有C ++ 0x RVALUE参考...)

最简单的方法是逐一转文,做std ::交换,这样

void test(std::string& res)
{
    std::string s;
    //...
    res.swap(s);
}

但是,比通过参考更自然,通常更方便地返回价值,因此我要实现的是:

std::string test()
{
    std::string s;
    //...
    return SOMETHING(s);
}

理想情况下,它只会做一个 swap 使用“返回值”,但我看不到如何在C ++中执行此操作。已经有auto_ptr可以移动而不是复制,我实际上可以使用 auto_ptr<string>, ,但是我想避免动态分配字符串对象本身。

我的想法是以某种方式“标记”一个字符串对象,该对象正在从函数中返回以允许 移动 返回时调用复制构造函数时的数据。因此,我最终获得了此代码,它确实可以完成我想要的:

struct Str
{
    struct Moveable
    {
        Str & ref;
        explicit Moveable(Str & other): ref(other) {}
    };

    Str() {}
    Str(const std::string& other) : data(other) {} // copy
    Str(Moveable& other) { data.swap(other.ref.data); } // move

    Moveable Move()
    {
        return Moveable(*this);
    }

    std::string data;
};

Str test()
{
    Str s;
    //...
    return s.Move(); // no allocation, even without NRVO
}

所以...所有这些都是有道理的,还是我缺少一些严重的问题? (我不确定例如没有终身问题)。也许您已经在图书馆中看到了这样的想法(书籍,文章...),可以给我参考吗?

编辑:正如@rstevens注意到的那样,此代码是MSVC特定的,并且不会在G ++下编译,而G ++不喜欢非临时性。这个 一个问题,但让我们假设此实现是MSVC特定的。

有帮助吗?

解决方案

Boost用途的实施在内部为图书馆进行移动语义仿真 boost.thread. 。您可能想查看实现并做类似的事情。

编辑: 实际上有一个库的积极发展 boost.move, ,因此您已经可以开始使用它。

其他提示

您是否在G ++上检查了此代码?

由于您使用临时对象(由S.Move()返回的一个)调用STR(Movable&)!

这不是标准的符合条件,也不由G ++支持。它得到了MSVC的支持! (MS称此功能为...)。

您是否真的确定按值返回是应用程序中的性能问题?这似乎是最简单/最简单的方法,当您升级到更现代的编译器时,您可以使用RVALUE参考。

我无法回答有关破坏令的问题 sMovable的参考。对于编译器,您可以将代码放入各种构造函数和灾难中,以查看订单是什么。即使看起来还不错,我仍然考虑使用您概述的一种普通图案之一,只是为了防止读者混乱,并可能破坏备用编译器。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top