Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.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++ 返回时交换STL?_C++_Stl_Swap_Return Value Optimization - Fatal编程技术网

C++ 返回时交换STL?

C++ 返回时交换STL?,c++,stl,swap,return-value-optimization,C++,Stl,Swap,Return Value Optimization,很抱歉问这么长的问题,但我尽量说清楚。这在某种程度上遵循了我之前的问题。我试图弄清楚如何在不依赖NRVO的情况下,在没有冗余内存分配的情况下从函数返回std::string。我不想依赖NRVO的原因是: 我们当前使用的编译器不支持它 即使支持它,也可能不总是在调试模式下启用它 在某些情况下,它可能会失败() 请注意,我需要一个与C++03兼容的解决方案(不幸的是,没有C++0x右值引用…) 最简单的方法是通过引用传递并执行std::swap,如下所示 void test(std::strin

很抱歉问这么长的问题,但我尽量说清楚。这在某种程度上遵循了我之前的问题。我试图弄清楚如何在不依赖NRVO的情况下,在没有冗余内存分配的情况下从函数返回std::string。我不想依赖NRVO的原因是:

  • 我们当前使用的编译器不支持它
  • 即使支持它,也可能不总是在调试模式下启用它
  • 在某些情况下,它可能会失败()
请注意,我需要一个与C++03兼容的解决方案(不幸的是,没有C++0x右值引用…)

最简单的方法是通过引用传递并执行std::swap,如下所示

void test(std::string& res)
{
    std::string s;
    //...
    res.swap(s);
}
但按值返回比按引用传递更自然、更方便,因此我希望实现以下目标:

std::string test()
{
    std::string s;
    //...
    return SOMETHING(s);
}
<>理想的是用“返回值”来做<代码>交换<代码>,但是我不知道如何在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的实现在内部使用移动语义模拟来模拟类似的库。您可能希望查看实现并执行类似的操作


编辑:实际上有一个正在开发的库,因此您可以开始使用它。

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


我无法回答关于
s
的销毁顺序与
Movable
参考的问题。对于编译器,您可以将代码放入各种构造函数和析构函数中,以查看顺序。即使看起来还行,我仍然会考虑使用一个你所概述的正常模式,只是为了防止读者混淆和可能打断另一个编译器。

< P>你在G++上检查这个代码吗?< /P> 因为您使用临时对象(s.Move()返回的对象)调用Str(Movable&)


这不符合标准,g++也不支持。它是由MSVC支持的!(微软称这是一项功能…。

我不确定你在问什么。你只需要修改你的代码吗?你说它完全符合你的要求,但据我所知,它不应该编译。你检查过你的字符串是否正确吗。如果是这样,将很少有额外的内存分配。另外,std::string的一些实现将字符串放入对象中(当字符串较短时),而不是为其分配内存。如果这些都是真的,那么你的优化尝试可能会增加成本,而不是降低成本。@Charles:代码是用来解释我要实现的目标的,问题是我是否看得对,是否已经有一些很好的实现。@Martin:MSVC在std::string上做得不好。也请看我前面提到的问题,因为我们已经在那里讨论了很多。最后,我不认为这种方法会增加成本,string::swap在某种程度上与COW不兼容吗?@David:在这种特殊情况下,我不同意你的观点。在这里,我更愿意确定发生了什么(交换),而不是依赖于编译器依赖的优化和每次读取汇编程序来确保它被优化。对我来说,这不仅仅是一个优化问题,因为它会影响典型的使用-除非开发人员知道按值返回是便宜的,否则他们会尽量避免这样做。人们仍然试图编写一些优化的代码,即使你说过早优化是有害的。你是对的,不会在g++下编译,我已经更新了这个问题。对于g++,可能可以做一些不同的事情,但我更感兴趣的是,是否在某些地方使用了类似的东西,而不是我的示例实现。