【问题标题】:Constructor, Copy Constructor and Stack Creation : C++构造函数、复制构造函数和堆栈创建:C++
【发布时间】:2013-04-29 19:15:09
【问题描述】:

这个问题是关于函数堆栈创建的。

假设我们创建一个函数 fn(int a,char b) 并从 main 调用 fn(A,B) ,在这种情况下,该函数被称为 fn。堆栈是使用返回地址、堆栈指针(等)创建的,其中创建局部变量和参数并在返回时被销毁。

我有几个问题: 1)对于我们的参数化构造函数假设

myClass{
    int a;
    char c;
public:
    myClass(int a,char c)
    {
        this->a=a;
        this->c=c;
    }
};

构造函数myClass(int a,char c) 是否也创建其函数堆栈并创建局部变量ac

2) 现在假设我们通过引用调用:我的函数是 fn(int* a,char* b)fn(int& a, char& b) 并分别通过 fn(&A,&B)fn(A,B) 从我们的 main 调用,在这种情况下,还将创建一个函数堆栈返回地址、SP 等。我的问题是,在这种情况下,是否会在堆栈上创建本地指针或引用(即创建指向传递对象的指针或引用的本地副本)。还是没有创建object的本地副本,直接传递指针或引用指向的原始对象?

3) 我们可以重载像fn(int& a,char& b)fn(int a,int b) 这样的函数吗?

谢谢

编辑

#include <iostream>

using namespace std;

void fn(int , char);
//void fn (int* a, char* c);
void fn (int& a, char& c);

int main()
{
   int a=10;
   char c= 'c';


  cout << "Inside main()" << endl;
  cout << hex << "&a : " << &a << endl;
  cout << hex << "&c : " << (int *)&c << endl;

   fn(a,c);
   //fn(&a,&c);
   fn(a,c);

    return 0;
    }


void fn (int a, char c)
{
    int tempInt;
    char tempChar;
    cout << "\n\nInside Call By Value Function " << endl;
    cout << hex << "&a : " << &a << endl;
    cout << hex << "&c : " << (int *)&c << endl;
    cout << hex << "&tempInt : " << &tempInt << endl;
    cout << hex << "&tempChar : " << (int *)&tempChar << endl;
    }

/*void fn (int* a, char* c)
{

    cout << "\n\nInside Call By Pointer Function " << endl;
    cout << hex << "*a : " << a << endl;
    cout << hex << "*c : " << (int*) c << endl;

    }
*/

void fn (int& a, char& c)
{

    cout << "\n\nInside Call By Reference Function " << endl;
    cout << hex << "*a : " << &a << endl;
    cout << hex << "*c : " << (int*) &c << endl;

    }

输出:

$ make
g++ -Wall Trial.cpp -o Trial
Trial.cpp: In function `int main()':
Trial.cpp:19: error: call of overloaded `fn(int&, char&)' is ambiguous
Trial.cpp:5: note: candidates are: void fn(int, char)
Trial.cpp:7: note:                 void fn(int&, char&)
Trial.cpp:21: error: call of overloaded `fn(int&, char&)' is ambiguous
Trial.cpp:5: note: candidates are: void fn(int, char)
Trial.cpp:7: note:                 void fn(int&, char&)
make: *** [Trial] Error 1

【问题讨论】:

    标签: c++ constructor


    【解决方案1】:

    构造函数myClass(int a,char c)是否也创建它的函数栈并创建局部变量ac

    是的,创建了一个函数堆栈,但 ac 不是函数堆栈的局部变量,它们是成员变量,并且生命周期不会随着构造函数的结束而结束。它们在所属的类实例的整个生命周期内都保持活动状态。

    还是没有创建对象的本地副本,直接传递指针或引用指向的原始对象?

    这称为通过引用传递。两种方式分别是:

    • 传递对象的地址或
    • 通过引用传递对象

    在任何一种情况下,都不会创建对象的副本。实际的对象可以在函数内修改,如果1函数中的指针指向被传递对象的地址,而2引用参数只是被传递对象的别名。

    我们可以重载像fn(int&amp; a,char&amp; b)fn(int a,int b) 这样的函数吗?

    不,你不能,因为当你调用它时编译器无法理解你打算调用哪个函数版本:

    int i = 10;
    int j = 20;
    fn(i,j);
    

    我误读为fn(int&amp; a,int&amp; b)fn(int a,int b) 而不是fn(int&amp; a,char&amp; b)fn(int a,int b)
    当然可以。它们具有不同的类型,因此有资格作为有效的重载函数。

    【讨论】:

    • 呵呵。我犯了同样的错误 :) 我重复了可能是因为我在你发帖时正在写答案。现在编辑它。
    • Can we overload a function like fn(int&amp; a,char&amp; b) and fn(int a,int b)? 我想我们不能,因为当我们调用 fn 时,这两种情况都是fn(A,B),我的编译器抱怨..$ make g++ -Wall Trial.cpp -o Trial Trial.cpp: In function int main()' : Trial.cpp:19: 错误: 调用重载fn(int&amp;, char&amp;)' is ambiguous Trial.cpp:5: note: candidates are: void fn(int, char) Trial.cpp:6: note: void fn(int*, char*) &lt;near match&gt; 三个重载函数fn(int a, int b), fn(int* a,int* b)fn(int&amp; a,int&amp; b)
    • @GauravK:您引用的代码示例与您提供的错误不匹配。请提供一个 online code sample 来演示错误。
    • @AlokSave 在主要问题陈述中查看我的编辑
    • @GauravK 您看到的错误是因为仅基于一个函数按值接收,另一个按引用接收,编译器无法决定调用哪个函数。但是,在您上面的评论中,第二个参数是一个 char & 与一个应该符合重载条件的 int。
    【解决方案2】:

    首先,您的概念有点不正确。

    即堆栈不是通过函数调用创建的。相反,每个执行线程都有自己的堆栈。它甚至在调用单个 main 时也存在。然而,当一个函数被调用时,一条 ACTIVATION 记录被压入堆栈。从函数返回时也会弹出相同的内容。

    所以对于

    1. 堆栈已经存在,每次函数调用都会在堆栈中推送一条激活记录。变量在对象的整个生命周期中都存在。

    2. 如果您的函数将指针作为参数(即通过引用调用),则会有一个指针变量被压入堆栈,该变量被传递原始变量的地址。原始变量保持不变,通过指针修改其值会改变原始变量。

    3. 只有在签名不同时才能重载函数。这意味着参数的类型、数量或顺序。在例如您引用了,无法区分传递的 int 是变量还是变量的地址。因此这个重载是行不通的。

    编辑:上面的第 3 点有轻微的错误。例如有问题引用的第二个参数不同,因此有资格作为有效重载。请注意,标准不仅仅是数据类型的名称(即 int 与 int * 也是不同的类型),而是给定输入值的事实,编译器应该能够区分并选择要调用的重载版本。

    【讨论】:

    • 我猜你说的是运行多个进程的大型复杂系统,对于简单的架构,例如 16 位微控制器,当你调用一个函数时,程序执行会转移到函数代码所在的地址存储,在此之前,某些参数被存储(这有助于返回到正确的位置,即下一个被调用的函数的命令)。为此,存储了返回地址,存储了一些寄存器内容,存储了堆栈指针,创建了局部变量,并在从函数返回时弹出。
    • 不,事实并非如此。堆栈是内存中程序映像的一部分,与架构无关。可能这应该有帮助。 en.wikipedia.org/wiki/Call_stack。您上面对每个函数调用的描述都是正确的,并且所有这些信息都存储在堆栈中。
    • 对于多进程系统,一个简单的嵌入式系统,只运行一个代码(无操作系统),即标准进程,对于多进程系统,每个进程维护自己的堆栈,函数可以创建它的自己的小堆栈(- 我可以说),带有返回地址,帧指针 n 全部 ..tenouk.com/Bufferoverflowc/Bufferoverflow2a.html
    • 是的 ..这是正确的 .. 堆栈在 RAM 中,不是为每个函数创建的,而是留在那里,该堆栈的函数存储其参数的部分 - 我作为它自己的小函数调用堆栈..
    • 刚才根据我之前的评论:fn(int a,char b) & fn(int&amp; a,char&amp; b) 将被称为 fn(A,B)main() 所以编译器会抱怨 which`fn`
    猜你喜欢
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-13
    • 2020-05-14
    • 1970-01-01
    相关资源
    最近更新 更多