首页 > 解决方案 > 构造函数初始化列表中 std::array 的 NRVO

问题描述

我知道std::array不做移动语义,因为它不是动态分配的。编译器是否为它做适当的 NRVO?在调用代码作为构造函数初始化列表的上下文中呢?

代码在下面和 goldbolt 上:https ://godbolt.org/z/je1Mvj15P 注意共享链接通过argv[1] = "12345678901234567890"。此外,它仅使用 -Og 来保持程序集的可读性。在 -O3 它开始展开循环等,但这不会影响我相信的问题。

构造函数初始化列表调用arr_(get_arr(s))别无选择,只能复制,因为移动它不可用。除非编译器正在执行完整的 NRVO(这是“非强制性的”,请参阅下面的评论)。

编译器资源管理器的输出在我看来似乎没有复制。

NRVO 会保存这个吗?这是惯用的/好吗?或者std::array这里是错误的选择?或者,这种使用函数调用初始化不可移动聚合成员并因此依赖 RVO 的方式可能是不明智/可靠的?

arr_在构造函数初始化列表中保留未初始化并将代码从get_arr构造函数体中移动会更好吗?像这样:https ://godbolt.org/z/jxv69YvK3

#include <algorithm>
#include <array>
#include <numeric>
#include <string>

std::array<std::byte, 20> get_arr(const std::string& s) {
    std::array<std::byte, 20> a;
    // a silly proxy algorithm for the real thing
    std::transform(s.begin(), s.end(), a.begin(), [](auto b) { return std::byte(unsigned(b) << 1U); });
    return a;
}

struct S {
    explicit S(const std::string& s) : arr_(get_arr(s)) {}
    std::array<std::byte, 20> arr_;
};

int main(int /*argc*/, char* argv[]) {
    // in reality we are reading about 600'000'000 strings  from a file
    S s(argv[1]);
    return static_cast<int>(s.arr_[19]);  // use it to avoid optimising away
}

标签: c++constructorstdarrayreturn-value-optimization

解决方案


推荐阅读