Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.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++ 删除了所有自动生成的构造函数/运算符的类仍然可以从函数返回吗?_C++_Return Value_C++17_Deleted Functions - Fatal编程技术网

C++ 删除了所有自动生成的构造函数/运算符的类仍然可以从函数返回吗?

C++ 删除了所有自动生成的构造函数/运算符的类仍然可以从函数返回吗?,c++,return-value,c++17,deleted-functions,C++,Return Value,C++17,Deleted Functions,最近,我遇到了这个描述如何初始化非默认可构造元素的std::array。我并不感到惊讶,因为这个答案显然不起任何作用 相反,它使用聚合初始化构造一个临时的std::array,然后在函数返回时移动(如果move构造函数可用)或复制到命名变量中。所以我们只需要move构造函数或copy构造函数就可以了 或者我是这么想的 然后出现了一段令我困惑的代码: struct foo { int x; foo(int x) : x(x) {} foo() = delete; f

最近,我遇到了这个描述如何初始化非默认可构造元素的
std::array
。我并不感到惊讶,因为这个答案显然不起任何作用

相反,它使用聚合初始化构造一个临时的
std::array
,然后在函数返回时移动(如果move构造函数可用)或复制到命名变量中。所以我们只需要move构造函数或copy构造函数就可以了

或者我是这么想的

然后出现了一段令我困惑的代码:

struct foo {
    int x;
    foo(int x) : x(x) {}
    foo() = delete;
    foo(const foo&) = delete;
    foo& operator=(const foo&) = delete;
    foo(foo&&) = delete;
    foo& operator=(foo&&) = delete;
};

foo make_foo(int x) {
    return foo(x);
}

int main() {
    foo f = make_foo(1);
    foo g(make_foo(2));
}
所有五个特殊成员构造函数/运算符都被显式删除,所以现在我不能从返回值构造对象,对吗

错。

令我惊讶的是,它是用gcc(使用C++17)编译的


为什么要编译?显然,要从函数
make_foo()
返回
foo
,我们必须构造一个
foo
。这意味着在
main()
函数中,我们正在从返回的
foo
分配或构造一个
foo
。这怎么可能

欢迎来到的精彩世界(C++17新增。另请参见)

在所有这些情况下,您都是从类型为
foo
的prvalue初始化
foo
,因此我们只需忽略所有中间对象,直接从实际的初始值设定项初始化最外层的对象。这完全等同于:

foo f(1);
foo g(2);
我们甚至不考虑移动构造函数在这里——所以它们被删除的事实并不重要。具体的规则是,只有在这一点之后,我们才考虑构造函数并执行重载解析。

注意,在C++复制17之前(确保复制拷贝之前),您可能已经返回具有支撑的init列表的对象:

foo make_foo(int x) {
    return {x}; // Require non explicit foo(int).
                // Doesn't copy/move.
}
但用法会有所不同:

foo&& f = make_foo(1);
foo&& g(make_foo(2));

尝试使用
-std=c++11
-std=c++14
标志编译以观察不同的结果。
foo和&f
的生存期是否以与
const foo&f
相同的方式延长?
foo&& f = make_foo(1);
foo&& g(make_foo(2));