2014-11-05 20 views
13

Yani C++ kod biraz: GCC 4.8 ve VS 2013 ile iyi derlerGCC 4.8 std :: string yapıcısı için kötü kod üretir?

void func(const std::string& theString) 
{ 
    std::string theString(theString); 
    theString += " more string"; 
    std::cout << theString; 
} 

. C++ bilgimden kod, theString yerel değişkeni ile tamamlandı ve kapsam, theString işlev argümanından gizleniyor. theString yapısında, yalnızca theString kapsamı, std::string yapıcısına iletilen işlev argümanıdır. Oluşturulan std::string daha sonra kapsam içine giren ve daha sonra kodda kullanılan theString olan theString olarak adlandırılmıştır. Uf!

Ancak GCCstd::string yapıcıya iletilen theString gibi hareket gibi görünüyor (henüz inşa edilmemiştir) yerel theString çökmesine derlenmiş programı neden oluyor. VS 2013 ile kod derler ve çalışır.

Yani,

  1. benim kod doğru mu? Yoksa spesifik olmayan bir şey yapıyorum, yani GCC davranışı tanımsızdır.
  2. Bu GCC'de bir hata mı?
+4

En azından kodunuz berbat. Bu şekilde asla kodlanmamalısınız, çünkü okunamaz (insanlar için). –

+15

1. No. 2. Hayır. Bir dizeyi (başlatılmamış) kendisiyle başlatıyorsunuz. – juanchopanza

+0

Böylelikle, eğer varsa VS2013 içinde hata daha olasıdır. Ama kodun yanlış. –

cevap

30

Hayır, kodu geçersiz. C++ Standardına göre

(beyan 3.3.2 Noktası)

1 The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below.

[ Example: 
int x = 12; 
{ int x = x; } 

Here the second x is initialized with its own (indeterminate) value. —end example ]

ve (3.3.3 Blok kapsamı, # 2)

A parameter name shall not be redeclared in the outermost block of the function definition nor in the outermost block of any handler associated with a function-try-block.

+2

Bu örnek için '3.3.2' içindeki kurallı sorular şunlardır: C++ 11 için [Başlatma lvalue-to-rvalue dönüşümünü gerektirir mi? Int x = x; 'UB?] (Http://stackoverflow.com/q/14935722/1708801) ve C++ 14 için [C++ standardı, C'deki belirsiz değerlerin ve tanımlanmamış davranışların kullanımına göre değişmiştir. ++ 1y?] (http://stackoverflow.com/q/23415661/1708801) –

14

Bu, undefined behaviour in C++ dur. paxdiablo C++ 03 standardına aktarmaktadır:

The point of declaration for a name is immediately after its complete declarator (clause 8) and before its initializer (if any) ...

Example:

int x = 12; 
{ int x = x; } 

Here the second x is initialized with its own (indeterminate) value.

2

rağmen Mevcut cevaplar temel olarak doğrudur, bu tanımlanmamış bir davranıştır, çünkü belirsiz bir değer kullanıyorsunuz, detaylar biraz daha ilgili. İlkel türler için, Does initialization entail lvalue-to-rvalue conversion? Is int x = x; UB? ya da Has C++ standard changed with respect to the use of indeterminate values and undefined behavior in C++1y? ya da davranışların neden tanımlanmadığını anlamak için yeterli ayrıntı sağladığına inanıyorum.

Kullanıcı tanımlı bir tür için, ancak ayrıntıların yeterli olduğunu düşünmüyorum.

And if so, what is the semantics of the self-initialization of UDT?

ve sadece referans ve adres yapım aşamasında sınıfın alındığı bir örnek sağlar ve cevap diyor: Biz sorar hangi defect report 63: Initialization of class from self bu oldukça eski ama ilgili de görebileceğiniz

3.8 basic.life paragraph 6 indicates that the references here are valid. It's permitted to take the address of a class object before it is fully initialized, and it's permitted to pass it as an argument to a reference parameter as long as the reference can bind directly.

Nesne yapım aşamasında olduğundan ve depolama alanı tahsis edildiğinden, ancak başlatma işlemi tamamlanmadığı için kullanım ömrü başlamadığından, 3.8Nesne kullanım ömrü bölümüne atıfta bulunmaktadır.Biz bölümünden 3.8 gelen paragrafta 6 bakarsak

diyor (vurgu benim):

Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise, such a glvalue refers to allocated storage (3.7.4.2), and using the properties of the glvalue that do not depend on its value is well-defined. The program has undefined behavior if:

ve şunları içerir: başlatma tamamlandıktan

the glvalue is used to access a non-static data member or call a non-static member function of the object,

Yani önce alamaz std::string'un kopya yapımı sırasında açıkça gerekli olan statik olmayan bir veri üyesinin değeri.

İlgili konular