与类的成员复制混淆

发布于 2024-12-04 20:19:15 字数 588 浏览 0 评论 0原文

研究了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;
}

那么我在哪里没有得到这些概念。请建议其他示例(如果可能),以便我更好地理解。

After studying the member copying and the assignment operator in C++,
and looking at " member copying of class " which explains the conditions where default assignment operator cannot be generated. I am not very clear about the concepts as the following example I tried actually works on 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;
}

So where am I not getting the concepts. Please suggest other examples (if possible) so that I can understand better.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

千纸鹤带着心事 2024-12-11 20:19:15

Y y2 = y1; 不是赋值。这是一个复制构造函数调用。如果在同一行声明并初始化变量,则会调用单参数构造函数,并将等号右侧作为参数。 Y 并不能阻止默认复制构造函数被实例化(和调用)。

尝试以下操作:

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

这应该会失败,尽管我现在无法测试它。

Y y2 = y1; is not an assignment. It's a copy constructor call. If you declare and initialize a variable on the same line, a one parameter constructor is called with the right hand side of the equals sign as the parameter. There's nothing about Y that prevents the default copy constructor from being instantiated (and called).

Try the following:

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

This should fail, although I can't test it right now.

唯憾梦倾城 2024-12-11 20:19:15
class Y{
  int& x;

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

x 是 int 的引用变量。现在您将其初始化为 v1,这意味着 xv1 本身的别名。 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
       // ...
 };
class Y{
  int& x;

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

x is a reference variable to an int. Now you are initializing it to v1, which means x is an alias to v1 itself. The scope of v1 is in the constructor alone. With that said -

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

is equivalent to

 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
       // ...
 };
缱倦旧时光 2024-12-11 20:19:15
#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 ===|
*/
#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 ===|
*/
满意归宿 2024-12-11 20:19:15

您的类包含不能默认构造或赋值的成员,即:

  • 引用

  • 常量

因此,您的类不能隐含默认构造函数或赋值运算符。例如,您必须编写自己的构造函数:

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!

这会产生另外两个对象 yz,它们具有 ya == 15 和 < code>za == 15、ybzb 都是对 n 的引用。 (不要对最后的两种替代语法感到困惑;两者调用复制构造函数。)

Your class contains members which cannot be default-constructed or assigned, namely:

  • References

  • Constants

Therefore, no default constructor or assignment operator can be implied for your class. For example, you have to write your own constructor:

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
  { }
};

It is clear that you cannot default-construct Foo (i.e. Foo x;). It is also clear that you cannot reassign objects of class Foo (i.e. x = y;), because you cannot reassign references or constants.

By giving your class a reference or a constant member, you actually confer reference or constant semantics on the class itself, if you will, so this should be a fairly immediate logical consequence. For example, reassignment probably doesn't even make sense semantically, because your class is supposed to embody a constant concept.

However, note that you can make copies of your class: That's because you can make "copies" of references (i.e. furhter aliases), and copies of constants. Therefore, a copy constructor is available implicitly, by simply applying copy-construction member-by member. So you can say:

int n;
Foo x(15, n);

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

This results in two further objects y and z which have y.a == 15 and z.a == 15, and y.b and z.b are all references to n. (Don't be confused by the two alternative syntaxes at the end; both invoke the copy constructor.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文