C++ 理解c+中的引用和副本时出现问题+;

C++ 理解c+中的引用和副本时出现问题+;,c++,visual-c++,C++,Visual C++,首先,如果我没有在问题标题中使用正确的术语,我道歉。这是完全可能的。我开始学习C++,我承认我在参考和拷贝方面经历了一段非常艰难的时期。关于我的以下代码,我有以下问题: 在main.c中,参数是传递给Carrier.add()函数(*it)、引用还是我放在向量中的plan对象的副本,还是其他什么 当此参数添加到承运商的计划向量(在承运商类中)时,是否添加了副本?既然我没有提供复制构造函数,也没有让它复制,那它是如何工作的呢?我认为它是自动生成的 如果这个太笼统,请忽略它。我想我的主要问题是我想/

首先,如果我没有在问题标题中使用正确的术语,我道歉。这是完全可能的。我开始学习C++,我承认我在参考和拷贝方面经历了一段非常艰难的时期。关于我的以下代码,我有以下问题:

  • 在main.c中,参数是传递给Carrier.add()函数(*it)、引用还是我放在向量中的plan对象的副本,还是其他什么

  • 当此参数添加到承运商的计划向量(在承运商类中)时,是否添加了副本?既然我没有提供复制构造函数,也没有让它复制,那它是如何工作的呢?我认为它是自动生成的

  • 如果这个太笼统,请忽略它。我想我的主要问题是我想/需要了解它是如何工作的,这就是我在试图自己找到问题答案时遇到的问题。有没有一种方法可以让VisualStudio在我的实际代码中以与编译器相同的方式生成构造函数,这样我就可以在调试模式下一步一步地遍历它们,看看它们是如何工作的。现在,当我调试时,我很难判断是否调用了编译器生成的复制构造函数(如果真是这样的话)

  • 这是我的密码:

    main.c

    #include "stdafx.h"
    #include <iostream>
    #include "Plan.h"
    #include "Carrier.h"
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
        std::vector<Plan> plans;
    
        for (int i = 0; i < 4; ++i) {
            Plan p(i);
            plans.push_back(p);
        }
    
        Carrier c(5);
        for(std::vector<Plan>::iterator it = plans.begin(); it != plans.end(); ++it) {
                //my question is about the line directly below this comment
            c.add(*it);
        }
        return 0;
    }
    
    Plan.cpp

    #include "Plan.h"
    
    Plan::Plan(int i)
    {
        id = i;
    }
    
    Carrier.h

    #pragma once
    #include <vector>
    class Plan;
    class Carrier
    {
    private:
        int id;
        std::vector<Plan> plans;
    public:
        Carrier(int i);
        void add(Plan p);
    };
    
    (1) 由于
    Carrier::add
    不通过引用获取其参数,因此传递给它一个副本。要使其引用,请将其签名更改为

    void Carrier::add(Plan const &p);
    
    (2) 当您执行
    推回
    时,无论您是通过引用还是通过值/副本传递
    计划,都会创建副本;这是
    std::vector
    (以及所有其他标准容器)语义的一部分。复制构造函数由编译器自动生成

    (3) 我不是VC++用户,但编译器将生成的复制构造函数与

    Plan::Plan(Plan const &other)
     : id(other.id)  // there's only one member,
                     // but other members would be treated the same
    {}
    

    在空的主体中,您可以添加一条打印语句,指示调用了复制构造函数,但这不是防水的;在某些情况下,C++被允许执行复制优化优化,这意味着实际复制被跳过。

    < P>在回答您的第一个问题时,该计划对象是通过值传递的,因此它是传递给函数的对象的<强>拷贝>强>。 如果需要引用,则需要创建如下函数:

    void Carrier::add(Plan const & p)
    
    在这里传递常量对象计划是因为在函数中没有对其进行任何更改。在C++中,这是一个很好的实践,如果你不打算改变一个参数,并通过引用或指针传递它,就让它成为代码> const 在回答第二个问题时,将向本例中的容器(std::vector)传递一个副本

    在main.c中,参数是传递给Carrier.add()函数(*it)、引用还是我放在向量中的plan对象的副本,还是其他什么

    这是一份副本,因为您已将
    add()
    声明为
    void add(计划p)。如果要传递引用,则应将其声明为
    void add(Plan&p)

    当此参数添加到承运商的计划向量(在承运商类中)时,是否添加了副本?既然我没有提供复制构造函数,也没有让它复制,那它是如何工作的呢?我认为它是自动生成的

    对。编译器会为您生成它。有关更多详细信息,请参阅

    有没有一种方法可以让VisualStudio在我的实际代码中以与编译器相同的方式生成构造函数,这样我就可以在调试模式下一步一步地遍历它们,看看它们是如何工作的


    据我所知,您不能在Visual studio中将其指定为包含自动生成的复制构造函数的代码的设置。

    1-
    *它
    正在取消对
    计划
    向量的元素的引用,并通过值将它们传递给
    c。add
    。因此,没错,
    计划
    向量的每个元素的一个副本在变量
    p
    (添加
    方法的参数)中临时构造,然后添加到
    载体
    类的
    计划
    向量中

    2-没错,添加了一份副本。不提供复制构造函数时的默认行为是复制所复制对象的每个属性。您可以通过提供复制构造函数来修改此行为


    3-不难理解编译器生成的复制构造函数是如何工作的。只要假设传递对象的每个属性都被复制到其复制构造函数被调用的对象。

    为了理解
    按值传递
    按引用传递
    ,您需要知道什么是引用<代码>引用
    与相同内存位置的别名类似

    虽然下面的代码与您的问题无关,但我还是特意举了一个简单的例子来说明发生了什么

    #include<iostream>
    void foo(int , int & ); //Declaration of foo
    
    void foo(int copy, int &reference)
    {
              copy++; // Updates the Local Variable Copy 
              reference++;  // Updates x
    }
    
    int main(){
        int x=10;
        int &reftox=x; // reference to x
        foo(x,reftox);
        std::cout << x;
    }
    
    #包括
    无效foo(int,int&)//富国宣言
    void foo(整数副本、整数和参考)
    {
    copy++;//更新局部变量copy
    reference++;//更新x
    }
    int main(){
    int x=10;
    int&reftox=x;//对x的引用
    foo(x,reftox);
    
    std::难道非标准VC++扩展和STL的混合很奇怪吗……问题标题中的术语很完美,这是一个措辞很好的问题。+1。@Etienne-Ha。是的,我正在使用一本使用STL和gcc的书,但我在windows上,所以我只是在使用visual studio。我不应该使用STL吗?Mingw是一个可以尝试的替代方案。使用STL没有什么错。是的,你绝对应该使用STL。你应该避免使用
    \u tmain
    (更喜欢一个普通的
    int main(int argc,char*argv[])
    )。去掉stdafx.h,你可能不需要它。
    void Carrier::add(Plan const & p)
    
    #include<iostream>
    void foo(int , int & ); //Declaration of foo
    
    void foo(int copy, int &reference)
    {
              copy++; // Updates the Local Variable Copy 
              reference++;  // Updates x
    }
    
    int main(){
        int x=10;
        int &reftox=x; // reference to x
        foo(x,reftox);
        std::cout << x;
    }