Domanda

ho provato un esempio vivo di seguito:

typedef struct point
{
    int x;
    int y;
} point;

void cp(point p)
{
    cout<<p.x<<endl;
    cout<<p.y<<endl;
}

int main()
{
    point p1;
    p1.x=1;
    p1.y=2;
    cp(p1);
}

Gli questo è risultato stampato out:

1
2

che è quello che mi aspettavo. La mia domanda è: fa parametro p ottenere la copia completa dell'oggetto p1? Se è così, mi chiedo se questa è una buona pratica? (Ho assunto quando lo struct ottiene grandi dimensioni, questo creerà un sacco di copia spese generali).

È stato utile?

Soluzione

Non c'è niente di sbagliato con il passaggio struct come parametri. Tutto è passato per valore in C ++ così una copia completa è infatti fatta.

Lo struct hai dato nel tuo esempio è piccola, quindi probabilmente non è un problema se si passa per valore. Ma se si lavora con strutture di dati più grandi, si consiglia di passare per riferimento.

Attenzione però, passando per mezzo di riferimento che se si modifica lo struct all'interno della vostra funzione, lo struct originale verrà modificato. Assicurarsi di utilizzare la parola chiave const in tutti i casi in cui non si modifica lo struct. Questo vi darà un'informazione immediata su se le funzioni fanno modificare le informazioni oppure no.

Il vostro esempio potrebbe essere modificato per lavorare con i riferimenti in questo modo:

typedef struct point
{
    int x;
    int y;
} point;

void cp(const point& p) // You can know that cp doesn't modify your struct
{
    cout<<p.x<<endl;
    cout<<p.y<<endl;
}

void mod_point(point& p) // You can know that mod_points modifies your struct
{
    p.x += 1;
    p.y += 1;
}

int main()
{
    point p1;
    p1.x=1;
    p1.y=2;
    cp(p1);
    mod_point(p1);
    cp(p1); // will output 2 and 3
}

Altri suggerimenti

Sì, non c'è niente di sbagliato in questo e sì, p è una copia completa del p1. Non lo definirei un struct con due ints grande, ma se il struct fa ottenere grandi e se non è necessario modificarlo nel corpo della funzione si potrebbe considerare passando per riferimento const:

void cp(const point& p)
{
    // ...
}

Prima di dare una risposta alla tua domanda (a trovarlo alla fine di questo post), ecco un breve riassunto delle possibilità che hai per il passaggio di argomenti a una funzione:


1. oggetti Copy-costruiti (pass-by-value):

void cp(point p);

Questa è pass-by-value. Un oggetto point temporanea si crea e copia-costruito da qualsiasi oggetto point si passa in cp. Una volta foglie esecuzione della funzione cp, l'oggetto temporaneo viene distrutto.

Si noti che perché la funzione opera su una copia di ciò che è stato passato alla funzione, è possibile modificare l'oggetto point locale tanto quanto si vuole, l'oggetto originale del chiamante non sarà influenzato. Non c'è modo di modificare questo comportamento con i parametri di passaggio per valore.


2. Riferimenti agli oggetti (passaggio per riferimento):

void cp(point& p);

Questo è passare per riferimento. L'oggetto effettivo passato alla funzione è disponibile (e potenzialmente soggetta a modifiche) all'interno della funzione. Se non si desidera che la funzione di essere in grado di cambiare il passato-in oggetto, dichiarare il parametro come const point&:

void cp(const point& p);

3. Puntatori a oggetti (passaggio per riferimento):

void cp(point* p);

Questo è anche passaggio per riferimento, con alcune differenze. Una differenza notevole è che è possibile passare un puntatore nullo alla funzione. Questo non è possibile con i riferimenti, perché i riferimenti deve essere inizializzato e non possono essere sia collegato anche in seguito. - Come con riferimenti, se si vuole cp rifiutare di cambiare il passato-in point, dichiarano come const:

void cp(const point* p);

risposta alla vostra domanda:

parametri Pass-by-valore non sono intrinsecamente male in alcun modo. Naturalmente, ci sono tipi per cui copia costruzione è costoso (oggetti esempio molto grandi o complessi), o dove ha alcuni effetti collaterali (ad esempio con std::auto_ptr). In questi casi, si deve fare attenzione. In caso contrario, è solo un'altra caratteristica del C ++, che ha i suoi usi perfettamente ragionevoli.

void cp(point p){
}

ottiene per valore

void cp(point *p){
}

ottiene per riferimento

Proprio come qualsiasi altra variabile di dati.

In java lo scenario è diverso. oggetti che passano vanno sempre per riferimento.

Nel caso in cui la si struct punto è passato "per valore", che significa, che l'intera struttura viene copiato. Per i grandi tipi di dati, questo può davvero essere lento.

Si può considerare passando l'oggetto per riferimento

void cp(point& p) // p may be altered!

o essere di riferimento const

void cp(const point& p) // p may not be altered!

vedere le possibilità per evitare di passare gli oggetti per valore. L'oggetto non è solo 'copiato', ma è copia costruito. Quindi, si tratta di chiamare costruttore di copia e la catena di costruttori di copia se l'oggetto è costituito o derivato di più oggetti. Passare per riferimento, se possibile.

cp vuoto (punto & p const) const {

    cout << p.x << endl;
    cout << p.y << endl;

}

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top