【问题标题】:Why can this code elide a copy? [duplicate]为什么这段代码可以省略副本? [复制]
【发布时间】:2011-07-14 08:09:22
【问题描述】:

可能的重复:
constructor invocation mechanism
Why is it an error to use an empty set of brackets to call a constructor with no arguments?

为什么这个code 可以忽略A 的所有副本?

#include <iostream>

class A
{
public:
  A() {}
  A(const A&) { std::cout << "Copy" << std::endl; }
};

class B
{
public:
  B(const A& a_) : a(a_) {}
private:
  A a;
};

int main()
{
  B b(A());
}

这段代码显然没有复制A,并且在 ideone 的 gcc 3.4 下不输出任何内容。

【问题讨论】:

    标签: c++ most-vexing-parse


    【解决方案1】:

    问题不是复制省略,而是声明的含义:

    B b(A());
    // To get it working the way you expect [1]
    B b = B(A());
    // Or the slightly more obtuse.
    B b((A()));
    

    对编译器来说是一个函数声明。谷歌/搜索最令人烦恼的解析。 C++ FAQ lite 中的更多内容,包括解决方法。


    [1]:这不完全相同,因为这需要从AB隐式转换。如果B 被定义为:

    class B {
      A a;
    public:
      explicit B(const A& a_) : a(a_) {}
    };
    

    那么这将不是一个替代方案。

    【讨论】:

      【解决方案2】:
      B b(A());
      

      你认为这声明了一个变量?没有。

      它声明了一个函数b,其返回类型为B,并接受一个A (*)()类型的参数。

      看到这个话题:


      因此,如果您想声明一个变量,请在A() 周围加上一个额外的大括号:

      B b((A())); //it declares an object
      

      【讨论】:

      • 或者,不添加括号,而是使用等号:B b = A();几乎等同于 B b(( A() ));(仅当 B(A) 构造函数显式时才存在差异)
      • @David,为什么几乎?两者完全相同。我认为explicit 不是标准的 C++。
      • @iammilind:您可以将构造函数标记为显式,然后隐式转换不会使用它。如果B 被声明为struct B { explicit B( A const &amp; ) {} };,那么B b(( A() )); 将起作用(代码显式请求该构造函数),而B b = A(); 不会,因为没有从AB 的隐式转换。 B b = A(); 被编译器处理为B b = B(( A() ));,其中左侧转换是隐式
      【解决方案3】:

      用途:

      B b((A()));
      

      你的行是一个函数声明。不幸的是,C 允许在函数内部声明函数(顺便说一句,这对我来说似乎毫无用处),因此出于向后兼容性的原因,C++ 允许这样做。您可以使用额外的括号强制执行变量定义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-18
        • 2023-02-08
        • 2023-04-10
        相关资源
        最近更新 更多