调用函数时MSVC未省略拷贝,是否符合C++标准?
MSVC临时对象拷贝行为是否符合C++标准?
以下是测试代码:
#include <cstdio> struct Foo { ~Foo() { printf("~Foo\n"); } }; void foo(Foo) { } int main() { foo(Foo()); }
按照C++标准的**复制消除(Copy Elision)**规则,这段代码中main调用foo(Foo())时,编译器应当直接将临时对象Foo()作为foo的形参初始化,仅创建一个Foo实例,对应一次~Foo输出。
但实际测试中:
- 使用MSVC编译时,输出两行
~Foo,说明创建了两个Foo对象(推测一个是main中的临时对象,另一个是foo的形参); - 使用GCC编译时仅输出一行
~Foo,符合预期; - 若为
Foo添加空拷贝构造函数,MSVC也只会输出一行~Foo。
结论
这种情况不符合C++标准。
根据C++11及以后的标准规定,当临时对象被用来直接初始化同一类型的对象时(比如用临时对象作为函数实参初始化按值传递的形参),编译器必须执行复制消除,不允许生成额外的拷贝或移动操作,因此只能存在一个Foo实例。
MSVC在未显式定义拷贝构造函数时的行为违反了这一强制规则——它没有正确应用复制消除,反而生成了额外的拷贝。而当添加用户定义的拷贝构造函数后,MSVC才触发了合规的复制消除,这说明其默认行为存在标准合规性问题。
内容的提问来源于stack exchange,提问作者geza
相关产品推荐
相关产品推荐

