【问题标题】:Initializer lists and assignment overloading (operator =)初始化列表和赋值重载(运算符 =)
【发布时间】:2012-03-11 06:56:46
【问题描述】:

赋值运算符的重载会传播到初始化列表吗?

例如,假设一个类:

class MyClass {
    private:
        std::string m_myString; //std::string overloads operator =
    public:
        MyClass(std::string myString);
}

还有一个构造函数:

MyClass::MyClass(std::string myString)
 : m_myString(myString)
{
}

初始化器列表会计算出std::string 上的赋值运算符重载吗?如果没有,是否有解决方法?

特别是对于 GCC。

【问题讨论】:

  • 赋值运算符与什么有什么关系?一个对象只能通过构造函数来初始化;如果调用了赋值运算符,那只是因为您已经有一个对象实例。
  • @ildjarn 老实说,我是初始化列表的新手。我的理由是,因为它将替换构造函数主体中的m_myString = myString;(赋值),所以在初始化列表中有一个赋值of sorts
  • 我假设myString 的类型是std::string?你忘了给它一个类型。
  • 你错过了 C++ 的一个基本部分,assignmentintialization 之间的区别。 Initializer 列表进行初始化而不是赋值。
  • 在这种情况下,是的,它是一个复制构造函数;然而,在 real 代码中,您可能希望调用移动构造函数,而不是复制构造函数(假设您使用的是 C++11)。

标签: c++ gcc operator-overloading assignment-operator initializer-list


【解决方案1】:

我认为您缺少的是assignmentinitialization 之间的区别。

让我们看一个基本类型的简单示例:

int a = 10; // Initialization
a = 1; // Assignment

上面的例子很简单,不难理解。但是,当您进入用户定义的类型时,就没有那么简单了,因为对象是构造的

例如,让我们看看std::string

std::string s1("String1"); // Initialization (constructs s1 using constructor)
std::string s2 = s1; // Initialization (constructs s2 using copy constructor)
std::string s3(s2); // Initialization (constructs s3 using copy constructor)

s1 = s2; // Assigns s2 to s1 using assignment operator

这里的关键是operator= 在不同的上下文中表示不同的东西。这完全取决于左侧的内容。

  std::string s1 = "Hello"; // Lhs has std::string s1, so this is initialization
  s1 = "Bob"; // Lhs has only s1, so this is assignment

而初始化器列表只做初始化(因此得名初始化器列表)。

MyClass::MyClass(std::string myString)
 : m_myString(myString) // Initialization
{
}

请注意,当您在构造函数的主体中调用 operator= 时,您现在是在进行赋值而不是初始化。

MyClass::MyClass(std::string myString)
{
    // m_myString(myString); <-- Error: trying to call like a function
    m_myString = myString; // Okay, but this is assignment not initialization
}

【讨论】:

    【解决方案2】:

    我相信它会使用复制构造函数而不是赋值运算符。

    【讨论】:

      【解决方案3】:
      MyClass::MyClass(std::string myString)
       : m_myString(myString)
      {
      }
      

      注意这里有两份:一份用于初始化参数myString,一份用于初始化成员m_myString。你不想要那个。在 C++03 中,您将通过 const 引用获取参数:

      MyClass::MyClass(const std::string& myString)
       : m_myString(myString)
      {
      }
      

      而在 C++11 中,您将按值获取参数,然后手动将其移动到成员中:

      MyClass::MyClass(std::string myString)
       : m_myString(std::move(myString))
      {
      }
      

      【讨论】:

        猜你喜欢
        • 2014-11-20
        • 1970-01-01
        • 2011-12-24
        • 1970-01-01
        • 1970-01-01
        • 2017-06-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多