Neden CYBH davranış::memcpy TriviallyCopyable nesneler için tanımsız olur?
http://en.cppreference.com/w/cpp/string/byte/memcpy:
Eğer nesneleri TriviallyCopyable (örneğin, skaler, diziler, C-uyumlu yapılar) değilse, davranışı tanımsızdır.
Benim iş yerinde, uzun süre std::memcpy
TriviallyCopyable kullanarak takas nesneleri bit için kullandık:
void swapMemory(Entity* ePtr1, Entity* ePtr2)
{
static const int size = sizeof(Entity);
char swapBuffer[size];
memcpy(swapBuffer, ePtr1, size);
memcpy(ePtr1, ePtr2, size);
memcpy(ePtr2, swapBuffer, size);
}
ve asla herhangi bir sorun yoktu.
Olmayan TriviallyCopyable nesnelerle std::memcpy
istismar ve tanımsız davranış aşağı neden önemsiz olduğunu anlıyorum. Ancak, benim sorum:
Neden std::memcpy
kendi davranış olmayan TriviallyCopyable nesnelerle kullanıldığı zaman tanımsız olur? Neden bir standart belirlemek için gerekli gördükleri?
GÜNCELLEME
http://en.cppreference.com/w/cpp/string/byte/memcpy içeriğini bu yazı ve yazılan cevaplara yanıt olarak değiştirildi. Mevcut açıklama diyor ki:
Eğer nesneler değildir TriviallyCopyable (örneğin, skaler, diziler, C-uyumlu yapılar), davranışı tanımsız sürece programa bağlı değil etkileri yıkıcı hedef nesne (aday tarafından
memcpy
) ve ömür boyu hedef nesne (ki sona erdi, ama başladımemcpy
) tarafından başlatıldı bazı diğer araçlar gibi yerleştirme-yeni.
PS
@Cubbi: yorum
@Eğer bir şey İK aşağı garanti eğer RSahu, tüm programı tanımsız kılar. Ama Olası bu durumda İK etek ve cppreference buna göre değiştirilmiş gibi görünüyor katılıyorum.
CEVAP
Bir zamanlar aynı türde başka bir nesne içine olmayan basit copyable türde bir nesne, temel bayt kopyalayınbu nesne hayatta değil.
Örnek:
std::string str;
std::string str2;
std::memcpy(&str2, &str, sizeof str);
Depolama yeniden kullanarak str2
ömrü sona erdi:
Bir program depolama yeniden kullanarak, herhangi bir nesnenin ömrü sona erebilir nesneyi kaplar veya açıkça yıkıcı çağırarak önemsiz olmayan bir yıkıcı bir sınıf türünde bir nesne. Bir nesne için önemsiz olmayan bir yıkıcı bir sınıf türü, program değil açıkça depolama bir yıkıcı çağırmak için gerekli nesneyi yeniden ya; ne kadar örtülü ölü nesneleri çağırır anlatıyor İK çağırmak] serbest kaplar
Ancakbu nesne diriltilecek değiliz:
ömür boyubir nesnenin bir nesne çalışma zamanı bir özellik. Bir nesne bir sınıf ise önemsiz olmayan başlatma söyleniyor ya da belli bir tip veya kendi üyelerinden biri tarafından başlatıldı kurucu önemsiz bir varsayılan kurucu dışında. [Not: yapıcı hareket/önemsiz bir kopyasını başlatma önemsiz değil başlatma.— not end]
Türünde bir nesne ömrü
T
başlar:
- depolama ile türü için uygun uyum ve boyutu
T
elde edilen ve (1.2)- eğer nesne önemsiz olmayan başlatma, başlatma. tamamlayın.
Kod parçasında gördüğünüz gibi, önemsiz olmayan başlatma string
- yani yapıcı bir çağrı ile ilişkili yapılmamıştır. Böylece nesne yaşıyor ve kullanım değeri veremeyiz.
[temel.tipleri]/2 /3 memcpy
initializable çok basit copyable türleri için bytewise kopyalama tanımlayın:
Basit herhangi bir nesne (temel sınıf bir sınıfın bir başka) copyable yazın ya da nesnenin geçerli bir değeri olup olmadığını
T
, yazınT
temel bayt (1.7) nesne uyduruyor olabilirchar
unsigned char
dizisine kopyalanır. İçeriği isechar
unsigned char
dizi nesnesine kopyalar. nesne daha sonra orijinal değerini tutacaktır. [Örnek:#define N sizeof(T) char buf[N]; T obj; // obj initialized to its original value std::memcpy(buf, &obj, N); // between these two calls to std::memcpy, // obj might be modified std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type //holds its original value
— son örnek]
Basit copyable herhangi bir türü için
T
işaret etmek için iki işaretçilerT
, 25* *farklıobj1
obj2
nerede neobj1
ne de nesnelerobj2
taban sınıf bir sınıfın, temel bayt (1.7) yapıyorobj1
obj2
,obj2
sonradan tutacaktır kopyalanır kadarobj1
ile aynı değer.[Örnek:T* t1p; T* t2p; // provided that t2p points to an initialized object ... std::memcpy(t1p, t2p, sizeof(T)); // at this point, every subobject of trivially copyable type in *t1p contains // the same value as the corresponding subobject in *t2p
— son örnek]
Bu gibi görünüyor değil pek tutarlı ile yukarıdaki alıntı hakkında ömür boyu: değiliz arama *t1p
'In kopyası yapıcısı (veya herhangi bir decimal için bu konuda), ama görünüşe göre hazır için keyfi bir şekilde kullanılması, gibi *t2p
. Ancak, bu paragraf bu tanım zaten atlatmak gibi görünüyor.
Son olarak, kütüphane/derleyici mümkün olduğunu kaydetti ve basit copyable türleri için bazı standart kütüphane algoritmaları optimize etmek için izin alınması gerekmektedir.Basit copyable türleri işaretçiler std::copy
temel bayt memcpy
çağırabilir. Bu da swap
için de geçerlidir.
Bu yüzden sadece sopa kullanarak normal genel algoritmalar ve izin derleyici herhangi bir uygun düşük seviyeli optimizasyon - bu kısmen ne düşüncem basit copyable türü icat edildi için ilk başta: Belirleyici yasallık bazı iyileştirmeler. Ayrıca, bu dilin çelişkili ve underspecified parçaları hakkında endişelenmenize gerek beynin zarar önler.
Neden bu (kullanarak ) tanımsız davran...
Neden C# birbirleri ile iki nesne türl...
Neden bu döngü üretmek "uyarı: yi...
fancybox2 / fancybox sayfanın en üstün...
Neden aynı ASP.NET MVC eylem için aynı...