Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.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++ 为什么对于非内置类型,返回值应该是const,而对于内置类型,返回值应该不是const?_C++_Templates_Return By Value - Fatal编程技术网

C++ 为什么对于非内置类型,返回值应该是const,而对于内置类型,返回值应该不是const?

C++ 为什么对于非内置类型,返回值应该是const,而对于内置类型,返回值应该不是const?,c++,templates,return-by-value,C++,Templates,Return By Value,上的解决方案4和5提到: 对于非内置返回类型,按值返回通常应为常量 因为int已经是一个右值,所以输入'const'可能会干扰模板实例化,造成混淆、误导,并且可能会使人发胖 我有以下问题 我们在这里干预的是哪个模板实例化 究竟什么是误导,为什么 为什么要区分非内置和内置。我认为这是一个糟糕的做法 这是不正确的——GotW中相对较少的错误之一常量右值在C++03中是有问题的,在C++11中肯定非常糟糕 问题是,在C++03中,右值可以调用任何成员函数,即使是非常量。这很好,因为您可以“优化”或执

上的解决方案4和5提到:

对于非内置返回类型,按值返回通常应为常量


因为int已经是一个右值,所以输入'const'可能会干扰模板实例化,造成混淆、误导,并且可能会使人发胖

我有以下问题

  • 我们在这里干预的是哪个模板实例化
  • 究竟什么是误导,为什么
  • 为什么要区分非内置和内置。我认为这是一个糟糕的做法 这是不正确的——GotW中相对较少的错误之一<代码>常量右值在C++03中是有问题的,在C++11中肯定非常糟糕


    问题是,在C++03中,右值可以调用任何成员函数,即使是非常量。这很好,因为您可以“优化”或执行方法链和其他事情,这些都非常好,而且绝对有意义,但这也很糟糕,因为当您执行一些愚蠢的操作时,编译器无法捕捉到您,例如赋值或其他操作。一般来说,限制每个人做好事是个坏主意,因为打电话的人可能会做一些愚蠢的事情。用意是好的,但并不正确

    在C++11中,这是固定的,因为您可以禁止对右值调用成员函数,其次,为了使移动语义正确工作,右值必须是可变的。如果右值为
    const
    ,则不能从该右值获取资源

    值得注意的是,之所以不同,是因为原语类型总是在语言中内置了特殊的措词,例如,将赋值赋给右值是非法的,所以没有必要自己尝试通过使其
    const
    来强制执行


    至于模板实例化,我实际上不确定。当我开始编码C++时,这种做法已经被证明是坏的,所以这不是我必须处理的事情。我不同意将
    const
    放在独立于移动语义的返回值上的建议:该值已经是一个右值,因此不存在意外修改它的危险。这就是为什么要在非内置类型上放置一个
    const
    :它们可能包含某种形式的值后门。例如,
    std::vector
    有一个
    swap()
    方法,可用于“窃取”非常量值的内容:

    std::vector<int> f();
    std::vector<int> value;
    f().swap(value);
    
    没有
    std::skipws
    时,流是一个右值,不能绑定到
    std::operator>>(std::istream&,std::string&)
    的第一个参数,但使用操纵器的成员操作符返回对流的非常量引用

    内置类型上的
    常量实际上没有任何效果。特别是,当将函数的结果传递给函数模板时(在C++2003中),它无法区分传递的是
    const
    还是非
    const
    返回。因此,
    const
    似乎对内置返回有影响,尽管实际上没有影响


    正如我所说的,我不同意这个规则,在C++2011中,它肯定不成立,因为你希望能够移动一个非内置的,但是
    常量返回将阻止它。

    注意,在任何返回值上放置
    常量不再是一个好的做法,因为您有效地禁用了移动语义。所以至少你不必太担心@格曼尼克:但我还是很想理解这一点。另外,你能扩展一下你的评论(可能是一个答案)吗?const为什么会禁用移动语义?@Lazer移动构造函数通常可以作为交换来实现,但只有当构造函数参数为non-const时——如果它是const,你将无法交换,因为它是只读的。@hvd:Swapping实际上与此无关。移动只需要修改参数(使其不再拥有资源),而当参数为
    const
    时,就不能这样做。是否用交换完成的是无关的。@ gman NICG C++允许<代码>静态分析(t)< /代码>,不是吗?然后可以将它传递给
    T(const T&&)
    构造函数,以获得一个不常见的类似移动的构造函数。移动不需要修改参数,移动是允许的。如何禁止对右值调用成员函数?“问题是,在C++03中,右值可以调用任何成员函数,即使是非常量。”--也许我不理解你的意思,但这就是
    const
    -限定右值的原因,不是吗?你不能在
    const
    rvalues上调用非
    const
    成员函数。@MikeSeymour这是C++11中的新语法,我忘记了精确的语法,但它类似于
    void f()&{}
    void f()&&{}
    来重载rvaluence。@MikeSeymour但显然我猜得很好:这是正确的语法(至少正如在中提出的那样)@hvd:这是一个支持
    const
    rvalues的论点。但是,正如我所解释的,它弊大于利,即使在C++03中,即使忽略了您在C++11中引入的问题,也没有任何好处。
    int GetNumPoints() {
        return points_.size();
    }
    
    Return-by-value should normally be const for non-builtin return types ..
    
    std::vector<int> f();
    std::vector<int> value;
    f().swap(value);
    
    std::string word;
    std::istringstream("hello, world") >> std::skipws >> word;