C++ 按值返回ifstream编译

C++ 按值返回ifstream编译,c++,C++,我注意到我能够按值从函数返回std::ifstream,而编译器不会给我任何与已删除副本构造函数相关的错误。这不应该起作用,因为ifstreams不应该是可复制的,所以我认为它以某种方式内联了函数?有人对此有解释吗 我正在用苹果LLVM版本7.3.0(clang-703.0.31)运行MacOSX El Capitan 10.11.6++ ifstream enterFile(){ ifstream输入(“hello.txt”); 返回输入; } int main(){ ifstream f=e

我注意到我能够按值从函数返回
std::ifstream
,而编译器不会给我任何与已删除副本构造函数相关的错误。这不应该起作用,因为ifstreams不应该是可复制的,所以我认为它以某种方式内联了函数?有人对此有解释吗

我正在用苹果LLVM版本7.3.0(clang-703.0.31)运行MacOSX El Capitan 10.11.6++

ifstream enterFile(){
ifstream输入(“hello.txt”);
返回输入;
}
int main(){
ifstream f=enterFile();
弦线;
while(getline(f,line)){

cout复制构造函数可能会被删除,但移动构造函数是声明的且可访问的。当您从函数返回局部变量时,将首先执行重载解析,就像它是一个右值一样。它选择调用哪个c'tor。如果对象是可移动构造的(有一个可以绑定到右值引用的c'tor),代码将是格式良好的

即使完成了所有这些操作,RVO也可能被应用,对象根本不会移动。因此
f
input
虽然在不同的范围内,但将引用同一对象


这是C++14的要点。从C++17开始,由于保证了复制省略,甚至移动构造函数也不一定总是可用。如果您尝试返回纯右值,而不是指定的本地值,您会注意到这一差异。

复制构造函数可能会被删除,但移动构造函数是声明和可访问的。当您返回loca时函数中的l变量,重载解析首先像右值一样执行。它选择调用哪个c'tor。如果对象是可移动构造的(具有可绑定到右值引用的c'tor),则代码的格式将良好

即使完成了所有这些操作,RVO也可能被应用,对象根本不会移动。因此
f
input
虽然在不同的范围内,但将引用同一对象


这就是C++14的要点。从C++17开始,由于保证了复制省略,甚至move C'tor也不必总是可用。如果您尝试返回纯右值,而不是指定的本地值,您会注意到这一差异。

如果流不能复制,但可以移动,
输入由move构造函数返回
如果流
无法复制,但可以移动,
输入
由move constructor返回。我猜测了一些类似的内容,但我试图将事实明确化。例如,它看起来不像是在调用move constructor,因为那里有一些打印语句没有显示。我最后的猜测是RVO,但我尝试了使用
-fno elide构造函数禁用它是徒劳的。我有没有办法确定是什么特定功能导致了这一点?@gowrath-Print语句在哪里?您自己的代码移动
ifstream
。我从std::ifstream中派生了自己的类ifstreamv,以便打印调用了哪种类型的构造函数。实际上,一些进一步的调查显示它是RVO,如果不是,则调用move构造函数。我通过在从enterFile()返回时设置运行时条件来禁用RVO方法,它在移动构造函数中打印了我的print语句:)我沿着这些线猜到了一些东西,但我试图使事实显式化。例如,它看起来不像是在调用移动构造函数,因为我在那里有一些未显示的print语句。我最后的猜测是RVO,但我尝试使用
-fno el禁用它ide构造函数
无效。有什么方法可以确定导致这种情况的特定功能吗?@gowrath-Print语句在哪里?您自己的代码移动了一个
ifstream
。我从std::ifstream中派生了自己的类ifstreamv,以便打印调用了哪种类型的构造函数。实际上,一些进一步的调查显示了这一点是RVO,如果不是,则调用移动构造函数。我通过在enterFile()方法返回时设置运行时条件禁用了RVO,并且它在移动构造函数中打印了我的print语句:)
ifstream enterFile(){
    ifstream input("hello.txt");
    return input;
}


int main() {
    ifstream f = enterFile();
    string line;
    while(getline(f, line)) {
        cout << line << endl;
    }
    cout << "===== Done" << endl;
    return 0;

}