2011-04-13 48 views
3

首先,如果我在問題標題中沒有使用正確的術語,我表示歉意。完全有可能。我開始學習C++,並且我會承認我在引用和副本方面遇到了很多困難。在參考下面我的代碼,我有以下問題:問題理解引用和C++中的副本

  1. main.c中,是傳遞給Carrier.add()函數(*吧),參考或的副本說法計劃的對象,我把矢量,或其他東西?

  2. 當這個參數被添加到承運人的計劃矢量(在承運人類內)時,是否添加了一個副本?這是如何工作的,因爲我沒有提供拷貝構造函數或者告訴它拷貝?我認爲它是自動生成的?

  3. 如果過於籠統,請忽略此項。我想我的主要問題是我想/需要了解它是如何工作的,而這正是我自己試圖找出問題答案的地方。有沒有一種方法可以使Visual Studio在編譯器中以我的實際代碼生成構造函數,因此我可以在調試模式下逐步查看它們,看看它們是如何工作的。現在,當我調試時,我很難說出一個編譯器生成的拷貝構造函數被調用(如果這是所發生的事情)。

這裏是我的代碼:

的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.h

#pragma once 

class Plan 
{ 
private: 
    int id; 
public: 
    Plan(int id); 
}; 

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

Carrier.cpp

#include "Carrier.h" 
#include "Plan.h" 

Carrier::Carrier(int i) { 
    id = i; 
} 

void Carrier::add(Plan p) { 
    plans.push_back(p); 
} 
+1

非標準的VC++擴展和STL的混合很奇怪... – 2011-04-13 17:38:18

+1

問題標題中的術語是完美的,這是一個很好的措辭問題。 +1。 – 2011-04-13 17:43:36

+0

@Etienne - Ha。是的,我使用的是一本使用stl和gcc的書,但是我在windows上,所以我只是使用visual studio。我應該不使用stl嗎? – oob 2011-04-13 18:25:11

回答

3

(1)由於Carrier::add不通過引用採取它的參數,它是通過一個副本。將它取一個基準,改變其簽名,以

void Carrier::add(Plan const &p); 

(2)當執行push_back中,無論是否通過引用或值/複製傳遞Plan創建的副本;這是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++被允許執行優化,意味着實際的複製被跳過。

2

回答第一個問題時,該計劃對象是按值傳遞的,因此它是傳遞給該函數的對象的副本

如果你想要一個參考,你需要創建功能像這樣:

void Carrier::add(Plan const & p) 

你在這裏傳遞一個const對象計劃,因爲你沒有改變的功能什麼的。這在C++中被認爲是很好的做法,如果你不打算修改一個參數並通過引用或指針傳遞它,請將其設爲const

在回答你的第二個問題時,在這種情況下的容器(std :: vector)傳遞一個副本。

2

在main.c中,是將參數傳遞給Carrier.add()函數(* it),引用還是計劃對象的副本,我將其放入向量或其他東西中?

這是一個副本,因爲您聲明add()void add(Plan p);。如果您想傳遞參考,則應聲明爲void add(Plan& p);

當這個參數被添加到承運人的計劃載體(載體類內)時,是否添加了副本?這是如何工作的,因爲我沒有提供拷貝構造函數或者告訴它拷貝?我認爲它是自動生成的?

是的。編譯器爲您生成它。有關更多詳細信息,請參閱here

是否有一種方法可以使Visual Studio以我編寫的實際代碼的方式生成構造函數,因此我可以在調試模式下通過它們來查看它們是如何工作的。

據我所知,您不能在Visual Studio中將其指定爲包含自動生成的複製構造函數的代碼的設置。

2

1- *it正在引用plans向量的元素,並將它們傳遞給值爲c.add。所以,對,plans矢量的每個元素的副本臨時構建在變量p(參數add方法)中,然後添加到Carrier類的plans矢量中。

2-是的,一個副本被添加。當您不提供複製構造函數時的默認行爲是複製正在複製的對象的每個屬性。您可以通過提供複製構造函數來修改此行爲。

3-理解編譯器生成的複製構造函數是如何工作的並不難。假設傳遞的對象的每個屬性都被複制到其複製構造函數被調用的對象。

2

爲了理解pass-by-valuepass-by-reference您需要知道什麼是參考。 References就像aliases到相同的內存位置。

雖然下面的代碼與你的問題沒有任何關係,但我故意用一個簡單的例子來演示發生了什麼。

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

輸出將是11。有關您的問題的其餘疑問已經得到解答。