Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.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++ Visual Studio 2015中的返回值优化?_C++_Visual Studio_Visual C++_Visual Studio 2015 - Fatal编程技术网

C++ Visual Studio 2015中的返回值优化?

C++ Visual Studio 2015中的返回值优化?,c++,visual-studio,visual-c++,visual-studio-2015,C++,Visual Studio,Visual C++,Visual Studio 2015,在probject中,我使用了与以下类似的代码: class C { public: C() {} C(const C&) = delete; }; C f() { return C(); } int main() { f(); } 以前使用的Visual C++编译器(最多2013个),这从来都不是问题。但是当我尝试用新的Visual C++ 2015编译器编译它时,我得到以下错误: 1>c:\devel\c++11\playground\

在probject中,我使用了与以下类似的代码:

class C {
public:
    C() {}

    C(const C&) = delete;
};

C f() {
    return C();
}

int main() {
    f();
}

以前使用的Visual C++编译器(最多2013个),这从来都不是问题。但是当我尝试用新的Visual C++ 2015编译器编译它时,我得到以下错误:

1>c:\devel\c++11\playground\main.cpp(10): error C2280: 'C::C(const C &)': attempting to reference a deleted function
1>  c:\devel\c++11\playground\main.cpp(6): note: see declaration of 'C::C'
我不确定它以前为什么工作,但我假设由于返回值优化,调用了默认构造函数,而不是复制构造函数

C(C&&) = default;
C& operator=(C&&) = default;

是我使用的代码,甚至合法C++?如果不是,那么在我的类

C
不需要复制构造函数的情况下,实现这段代码的正确方法是什么?当然,我可以使用一个移动构造函数,但是我假设代码在C++ 11之前从来都不是有效的C++。由于删除了复制构造函数,因此需要定义移动构造函数

C(C&&) = default;
C& operator=(C&&) = default;
-有效
-不起作用,违反了第五条规则


注意:上述站点使用gcc,甚至不会编译,因此它不是Visual Studio特有的,这是一种已定义和预期的行为。

可能以前它曾为此选择隐式生成的移动构造函数,但在VS 2015中,隐式生成的移动构造函数因存在复制操作而被阻止,如果我没记错的话,这是符合标准的行为


因此,您只需要自己定义move构造函数,可能是a=默认构造函数。

函数参数和返回值是使用初始化的。复制初始化要求可以访问复制构造函数,即使它们被(N)RVO省略:

如果T是类类型,而other的类型不同,或者如果T是非类类型,但other的类型是类类型,则用户定义的转换序列可以从other的类型转换为T(或者如果T是类类型且有转换函数可用,则转换为从T派生的类型)并通过过载分辨率选择了最佳的。转换的结果(如果使用了转换构造函数,则为prvalue临时值)随后用于直接初始化对象最后一步通常是优化出来的,转换的结果直接在分配给目标对象的内存中构造,但即使没有使用,也需要访问相应的构造函数(移动或复制)。


“以前它设法为此选择隐式生成的移动构造函数”实际上在VS2013中根本没有隐式生成的移动构造函数(在这方面,它们不符合C++11标准)。他们最终添加了VS2015的功能。2013年CTP中不是添加了移动操作的隐式生成(处理=默认值)吗?如果它是在没有与复制操作进行poper合作的情况下添加的,那么如果原始海报使用此编译器版本,它可以解释行为的变化。这说明了如何修复它,但不解释它最初发生的原因。这可能与以前版本的VS。但是,如果没有复制构造函数,为什么代码首先要编译?在以前的版本中,这段代码不会编译。在VS2013之前的版本中,
delete
关键字不存在(,不删除指针),因此它不会编译。在VS2013中,它会因为我描述的原因而抱怨试图使用删除的函数。@CoryKramer,这不完全正确。我可以以我在问题中发布的示例为例,在VS2013中编译它,而在VS2015中它会产生编译错误。@fschoenm在这种情况下,我会将我的注释从“它不会编译”修改为“它不应该编译”,如果VS2013允许OPS代码编译,那么它是错误的,不符合C++ 11标准。但是这意味着在VisualStudio的以前版本中,行为总是非法的,因为没有复制构造函数。VisualStudio从来没有遵循C++标准的示例。这正是正在发生的事情。编译器要求复制构造函数可用,但从未实际调用它。@fschoenm否,以前的行为完全合法-您声明了复制构造函数,因此它是可访问的:使用它的返回语句没有导致错误。由于编译器应用了RVO,因此实际上没有调用构造函数,因此您没有提供实现这一事实并不重要。既然您正在声明copy constructed=delete,它就不再可访问,因此出现了错误。哦,这一点也不令人困惑。:/如果省略了它,那么它就不会导致错误,否则可能会引入意外的错误。如果我没记错的话,VS没有实现`=delete;`语法直到VS2013,所以当你说“在以前的Visual C++编译器中我使用(最多2013),这从来不是问题”时,你是指“在VS2013中,那不是问题”?在VS2013之前,我简单地使用了一个没有实现的拷贝构造函数声明,这样它会导致链接错误,如果它被实际使用了。