Путаница с копированием членов класса - PullRequest
1 голос
/ 16 сентября 2011

После изучения копирования членов и оператора присваивания в C ++, и глядя на « копирование члена класса », которое объясняет условия, когда оператор присваивания по умолчанию не может быть сгенерирован. Мне не очень понятны концепции, поскольку следующий пример, который я попробовал, на самом деле работает на g ++ 4.5

#include<iostream>
using namespace std;

class Y{
  int& x;
  const int cx;
public:
  Y(int v1,int v2)
    :x(v1),cx(v2)
  {}
  int getx(){return x;}
  int getcx(){return cx;}
};

int main()
{
  int a = 10;
  Y y1(a,a);
  Y y2 = y1;//assignment
  cout<<y1.getx()<<" "<<y1.getcx();
  return 0;
}

Так, где я не получаю понятия. Пожалуйста, предложите другие примеры (если это возможно), чтобы я мог лучше понять.

Ответы [ 4 ]

2 голосов
/ 16 сентября 2011

Y y2 = y1; не является назначением.Это вызов конструктора копирования.Если вы объявляете и инициализируете переменную в той же строке, вызывается конструктор с одним параметром, в котором в качестве параметра указывается правая часть знака равенства.* * * * * * * * * * * * * * * * *

* * * * * * * * * * * * * *1004* * * * * * * * * * * * * * * * * * * * * * * * * * *}}}

Y y1(10, 10);
Y y2(11, 11);
y2 = y1;

Это должно произойти, хотя я не могу проверить этопрямо сейчас.

1 голос
/ 16 сентября 2011
#include<iostream>
using namespace std;

class Y{
  int& x;
  const int cx;
public:
  Y(int v1,int v2)
    :x(v1),cx(v2)
  {}
  int getx(){return x;}
  int getcx(){return cx;}
};

int main()
{
  int a = 10;
  Y y1(a,a);
  Y y2 = y1;//NOT assignment. Object is yet to be constructed, so calls copy c'tor
  y2 = y1; // assignment operator is called
  cout<<y1.getx()<<" "<<y1.getcx();
  return 0;
}

/*
D:\Workspaces\CodeBlocks\Test\main.cpp||In member function 'Y& Y::operator=(const Y&)':|
D:\Workspaces\CodeBlocks\Test\main.cpp|4|error: non-static reference member 'int& Y::x', can't use default assignment operator|
D:\Workspaces\CodeBlocks\Test\main.cpp|4|error: non-static const member 'const int Y::cx', can't use default assignment operator|
D:\Workspaces\CodeBlocks\Test\main.cpp||In function 'int main()':|
D:\Workspaces\CodeBlocks\Test\main.cpp|20|note: synthesized method 'Y& Y::operator=(const Y&)' first required here |
||=== Build finished: 3 errors, 0 warnings ===|
*/
1 голос
/ 16 сентября 2011
class Y{
  int& x;

  public:
  Y(int v1,int v2)
    :x(v1),cx(v2)
  {} // v1 ceases to exist from this point
};

x является ссылочной переменной для int.Теперь вы инициализируете его как v1, что означает, что x является псевдонимом v1.Область действия v1 находится только в конструкторе.С учетом сказанного -

 Y y2 = y1;//assignment => Not assignment. It is initialization.

эквивалентно

 Y y2(y1);  // compiler is looking for the overloaded constructor ( ie. copy constructor in this case ).

 class Y{
      public:
       Y ( const Y & other ); // copy constructor
       // ...
 };
0 голосов
/ 16 сентября 2011

Ваш класс содержит члены, которые не могут быть созданы или назначены по умолчанию, а именно:

  • Ссылки

  • Константа

Поэтому для вашего класса нельзя подразумевать конструктор по умолчанию или оператор присваивания. Например, вы должны написать свой собственный конструктор:

class Foo
{
  const int a;
  int     & b;
public:
  Foo(int val, int & modify_me) :
    a(val) ,      // initialize the constant
    b(modify_me)  // bind the reference
  { }
};

Понятно, что вы не можете создать конструкцию по умолчанию Foo (т.е. Foo x;). Также ясно, что вы не можете переназначать объекты класса Foo (т.е. x = y;), потому что вы не можете переназначить ссылки или константы.

Давая вашему классу ссылку или константный член, вы фактически присваиваете ссылку или постоянную семантику самому классу, если хотите, поэтому это должно быть довольно непосредственным логическим следствием. Например, переназначение, вероятно, даже не имеет смысла семантически, потому что ваш класс должен воплощать постоянную концепцию.

Однако обратите внимание, что вы можете сделать копий вашего класса: это потому, что вы можете делать "копии" ссылок (то есть псевдонимов) и копий констант. Следовательно, конструктор копирования доступен неявно, просто применяя член-конструктор копирования. Таким образом, вы можете сказать:

int n;
Foo x(15, n);

Foo y(x);
Foo z = x;  // these two are identical!

Это приводит к двум другим объектам y и z, которые имеют y.a == 15 и z.a == 15, а y.b и z.b - все ссылки на n. (Не смущайтесь двумя альтернативными синтаксисами в конце; оба вызывают конструктор копирования.)

...