标签: copy-elision

什么是复制省略和返回值优化?

什么是复制省略?什么是(命名)返回值优化?他们意味着什么?

它们会在什么情况下发生?有什么限制?

c++ optimization c++-faq return-value-optimization copy-elision

350
推荐指数
4
解决办法
7万
查看次数

保证副本省略如何运作?

在2016年奥卢ISO C++标准会议上,标准委员会将一项名为" 保证副本省略"的提案通过简化的价值类别投票进入C++ 17.

保证副本省略如何运作?是否涵盖了某些已经允许复制省略的情况,或者是否需要更改代码来保证复制省略?

c++ copy-elision c++17

75
推荐指数
1
解决办法
7883
查看次数

在C++函数中"返回"的确切时刻

这似乎是一个愚蠢的问题,但是return xxx;在一个明确定义的函数中"执行" 的确切时刻?

请参阅以下示例以了解我的意思(现在直播):

#include <iostream>
#include <string>
#include <utility>

//changes the value of the underlying buffer
//when destructed
class Writer{
public:
    std::string &s;
    Writer(std::string &s_):s(s_){}
    ~Writer(){
        s+="B";
    }
};

std::string make_string_ok(){
    std::string res("A");
    Writer w(res);
    return res;
}


int main() {
    std::cout<<make_string_ok()<<std::endl;
} 
Run Code Online (Sandbox Code Playgroud)

我天真地期待发生的事情make_string_ok被称为:

  1. 构造函数res被调用(价值res就是"A")
  2. w调用构造函数
  3. return res被执行.应该返回res的当前值(通过复制当前值res),即"A".
  4. w被称为析构函数,值res变为"AB".
  5. 析构res函数被称为.

所以我希望"A"结果,但"AB" …

c++ object-lifetime language-lawyer copy-elision c++17

67
推荐指数
3
解决办法
4121
查看次数

C中的返回值优化和复制省略

有些人不知道可以通过C中的值传递和返回结构.我的问题是关于编译器在C中返回结构时制作不必要的副本.诸如GCC之类的C编译器是使用返回值优化(RVO)优化还是仅仅是C++概念?我读过的关于RVO和copy elision的所有内容都与C++有关.

让我们考虑一个例子.我目前正在用C 实现一个双重数据类型(或者更确切地说是float-float,因为我觉得它很容易进行单元测试).请考虑以下代码.

typedef struct {
    float hi;
    float lo;
} doublefloat;

doublefloat quick_two_sum(float a, float b) {
    float s = a + b;
    float e = b - (s - a);
    return (doublefloat){s, e};
}
Run Code Online (Sandbox Code Playgroud)

编译器是否会复制doublefloat我返回的值,还是可以省略临时副本?

在C中命名的返回值优化(NRVO)怎么样?我有另一个功能

doublefloat df64_add(doublefloat a, doublefloat b) {
    doublefloat s, t;
    s = two_sum(a.hi, b.hi);
    t = two_sum(a.lo, b.lo);
    s.lo += t.hi;
    s = quick_two_sum(s.hi, s.lo);
    s.lo += t.lo;
    s = quick_two_sum(s.hi, s.lo);
    return s; …
Run Code Online (Sandbox Code Playgroud)

c c++ struct return-value-optimization copy-elision

56
推荐指数
2
解决办法
4164
查看次数

什么是复制省略以及它如何优化复制和交换习惯用法?

我正在阅读复制和交换.

我尝试阅读Copy Elision上的一些链接,但无法弄清楚它的含义.有人可以解释一下这种优化是什么,特别是下面的文字是什么意思

这不仅仅是为了方便,而且实际上是一种优化.如果参数绑定到左值(另一个非常量对象),则在创建参数时会自动创建对象的副本.但是,当s绑定到rvalue(临时对象,文字)时,通常会省略该副本,从而保存对复制构造函数和析构函数的调用.在赋值运算符的早期版本中,参数被接受为const引用,当引用绑定到右值时,不会发生复制省略.这导致创建和销毁另外的对象.

c++ optimization copy-and-swap copy-elision

30
推荐指数
1
解决办法
8465
查看次数

我可以将不可移动且不可复制的函数结果复制删除为可选值吗?

我想存储一个不平凡的类型,它是不可移动且不可复制的std::optional。然而该对象是由自由函数构造的。(例子

struct Foo {
    Foo();
    Foo(Foo const&) = delete;
    Foo(Foo&&) = delete;
    Foo& operator=(Foo const&) = delete; // added for completeness
    Foo& operator=(Foo&&) = delete; // added for completeness
    ~Foo();
};
Foo foo();
Run Code Online (Sandbox Code Playgroud)

无需改变Foofoo()

感谢复制省略,我已经可以做到这一点:

Foo f1 = foo();
Run Code Online (Sandbox Code Playgroud)

这也可以编译,因为std::optional只要求存储的类型是可破坏的:

std::optional<Foo> f2;
f2.emplace();
Run Code Online (Sandbox Code Playgroud)

但我无法填写f2函数结果:

f2 = foo(); // no
f2.emplace(foo()); // no
Run Code Online (Sandbox Code Playgroud)

显然,因为这需要复制或移动Foo. 这可能是不可能的,但我是否忽略了一些事情?

c++ copy-elision stdoptional

28
推荐指数
3
解决办法
1555
查看次数

Clang和GCC vs MSVC和ICC:复制/移动构造函数中的static_assert是否需要工作,如果复制/移动省略也适用?

我有一个我static_assert的模板结构的移动构造函数.这是否static_assert需要编译器考虑,即使可以复制省略?

这是精简的场景:

#include <type_traits>

template<typename T>
struct X
{
  X(X&&) { static_assert(std::is_same<void, T>::value, "Intentional Failure"); }
};

auto impl() -> X<int>;    
auto test() -> decltype(impl())
{
  return impl();
}

int main()
{
  test();
}
Run Code Online (Sandbox Code Playgroud)

GCC和Clang同意评估static_assert并且无法编译.
另一方面,MSCV和ICC编译代码就好了.

有趣的是,当我删除move构造函数的定义时,只需将其声明为:

template<typename T>
struct X
{
  X(X&&);
};
Run Code Online (Sandbox Code Playgroud)

GCC和Clang现在也编译代码.因此,所有编译器似乎都同意移动构造函数的定义与复制省略无关.

问题:
如果static_assert复制/移动构造函数中有a ,即使可以复制/移动省略,标准是否要求对其进行评估?

c++ static-assert language-lawyer copy-elision c++11

24
推荐指数
1
解决办法
785
查看次数

从函数正确传播`decltype(auto)`变量

(这是“ decltype(auto)变量是否有实际用例?的后续文章)

考虑以下情况-我想将一个函数传递f给另一个函数invoke_log_return,该函数将:

  1. 调用f;

  2. 打印一些东西到stdout ;

  3. 返回的结果f,避免不必要的复制/移动并允许复制省略。

请注意,如果f抛出异常,则不应将任何内容打印到stdout。这是我到目前为止的内容:

template <typename F>
decltype(auto) invoke_log_return(F&& f)
{
    decltype(auto) result{std::forward<F>(f)()};
    std::printf("    ...logging here...\n");

    if constexpr(std::is_reference_v<decltype(result)>)
    {
        return decltype(result)(result);
    }
    else
    {
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

让我们考虑各种可能性:

  • f返回prvalue时

    • result 将成为一个对象;

    • invoke_log_return(f)将是一个prvalue(有资格使用复制省略)。

  • f返回左值x值

    • result 将作为参考;

    • invoke_log_return(f)将是一个左值x

您可以在godbolt.org上看到一个测试应用程序。如您所见, …

c++ copy-elision auto c++17 decltype-auto

24
推荐指数
1
解决办法
437
查看次数

MSVC 无法返回可以复制但不能移动的对象

在摆弄复制省略时,我遇到了这种奇怪的行为:

class Obj {
 public:
  Obj() = default;

  Obj(Obj&&) = delete;
  Obj(const Obj&) { std::cout << "Copy" << std::endl; }
};

Obj f1() {
  Obj o;
  return o; // error C2280: move constructor is deleted
}

Obj f2() {
  Obj o;
  return Obj(o); // this however works fine
}

int main() {
  Obj p = f1();
  Obj q = f2();

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

GCC 和 Clang 接受此代码并且能够在两种情况下使用复制省略。

f1()MSVC 中抱怨它无法返回,o因为Obj删除了 的移动构造函数。但是,我希望它能够依靠复制构造函数。这是 MSVC 中的错误还是这种期望的行为(我不明白)和 GCC/Clang …

c++ visual-c++ language-lawyer copy-elision c++17

23
推荐指数
2
解决办法
904
查看次数

通过隐式转换返回时是否需要复制构造函数?

以下代码在Visual C++ 2013中编译良好,但不在GCC或Clang下编译.

哪个是对的?
通过隐式转换返回对象时是否需要可访问的复制构造函数?

class Noncopyable
{
    Noncopyable(Noncopyable const &);
public:
    Noncopyable(int = 0) { }
};

Noncopyable foo() { return 0; }

int main()
{
    foo();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

GCC:

error: 'Noncopyable::Noncopyable(const Noncopyable&)' is private
  Noncopyable(Noncopyable const &);
  ^
error: within this context
 Noncopyable foo() { return 0; }
Run Code Online (Sandbox Code Playgroud)

铛:

error: calling a private constructor of class 'Noncopyable'
Noncopyable foo() { return 0; }
                    ^
note: implicitly declared private here
        Noncopyable(Noncopyable const &);
        ^
warning: C++98 requires an …
Run Code Online (Sandbox Code Playgroud)

c++ copy-constructor implicit-conversion copy-elision

22
推荐指数
2
解决办法
1741
查看次数