2012-01-09 15 views
5

tengo el siguiente código:alcances y C++ punteros

using namespace std; 
vector<string*> v; 
{ 
    string s = "hello"; 
    v.push_back(&s); 
} 
{ 
    string ss = "goodbye"; 
    v.push_back(&ss); 
} 

cout << v.at(0)->c_str() << endl; 
cout << v.at(1)->c_str() << endl; 

que imprime

goodbye 
goodbye 

si quito el alcance paréntesis que el código imprimirá

hello 
goodbye 

¿Qué ocurre exactamente cuando Dejo el primer alcance, que el puntero a la primera cadena ahora apunta a la segunda?

+1

UB, Luke! Esto es solo UB. Tuviste suerte de que tu computadora no explotara. –

+1

Le remito a la ahora famosa respuesta a esta pregunta: http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope – Benj

+0

Sí, [cruce las secuencias] (http://en.wikipedia.org/wiki/Proton_pack#Crossing_the_Streams) de nuevo. –

Respuesta

7

Los punteros almacenados se vuelven punteros colgantes después del alcance y cualquier intento de leer lo que señalan produce un comportamiento indefinido.

+0

eso fue lo que pensé que debería pasar, pero el hecho de que los resultados fueran constantes tuve que preguntar. – Bg1987

+2

comportamiento indefinido significa que cualquier cosa puede suceder, incluida la obtención de resultados uniformes y uniformes. Esta es una de las razones por las cuales el comportamiento indefinido es tan malo; es posible que ni siquiera lo note cuando escribe un programa, pero su programa puede fallar catastróficamente en otras circunstancias. – bames53

+0

@ Bg1987: comportamiento no definido no significa comportamiento aleatorio. La verdadera aleatoriedad no existe en realidad :) Significa que lo que sucederá no estará sujeto a ninguna regla (desde el punto de vista estándar), sino que la salida del compilador seguirá estando sujeta a las reglas de producción del código del compilador, por lo que el rango de los comportamientos que puede proporcionar es limitado. –

3

Lo que ocurre allí es un comportamiento indefinido, ya que s está fuera del alcance en el momento en que lo hizo referencia en la llamada al operador cout<<.

que no se desplome debido a s y sssucede que tiene la misma dirección con su arquitectura específica y la implementación de C++. En otras palabras, otros que intenten replicar su experimento en otras arquitecturas o con otros compiladores probablemente obtengan resultados diferentes.

2

Está desreferenciando dos punteros a dos objetos que se han destruido: este es un comportamiento indefinido. Cualquier cosa podría pasar aquí.

+0

con punteros que apuntan a una ubicación no válida no es un comportamiento indefinido; Deferirlos es –

+0

@phresnel, sí. Editado – hmjd

3

En la práctica, el sistema está reutilizando la memoria que utilizó para que la cadena s sostenga la cadena ss. Pero sucede que así es como el compilador administra la memoria; de acuerdo con el estándar C++, no puede confiar en dicho comportamiento y el resultado real del código que ha publicado no está definido.