[英]Strange behaviour of std::make_shared
我有一個非常奇怪的行為,我無法理解。
該測試通過:
CipString str = *std::make_shared<CipString>("Bye!").get();
EXPECT_EQ(static_cast<std::string>(str), "Bye!");
但這不是:
CipString *str = std::make_shared<CipString>("Bye!").get();
EXPECT_EQ(static_cast<std::string>(*str), "Bye!");
我收到一個錯誤:
預期:static_cast(* str)
這是:“ p \\ x15 \\ x97 \\ x1”
等於:“再見!”
CipString的代碼:
class CipString{
public:
CipString(const std::string& str) {
length = str.size();
string.reset(new uint8_t[length]);
std::copy(str.begin(), str.end(), string.get());
}
operator std::string() const {
std::string str("", length);
std::copy(string.get(), string.get() + length, str.begin());
return str;
}
uint16_t length; /**< Length of the String (16 bit value) */
std::shared_ptr<uint8_t> string; /**< Pointer to the string data */
};
這行:
CipString *str = std::make_shared<CipString>("Bye!").get();
創建一個shared_ptr,它在;
之后被銷毀;
。 之后, str
是一個懸空指針,您的測試通過訪問釋放的內存來調用未定義的行為。
您基本上是在聲明垃圾內存。
CipString str = *std::make_shared<CipString>("Bye!").get();
EXPECT_EQ(static_cast<std::string>(str), "Bye!");
分解為:
1)調用make_shared返回shared_ptr
2)獲取底層對象的地址
3)使用指向基礎對象的指針構造CipString
4)銷毀shared_ptr
很好
這分解為:
CipString *str = std::make_shared<CipString>("Bye!").get();
1)構造一個shared_ptr
2)獲取底層對象的地址
3)從中創建一個臨時CipString並將地址存儲在str中
4)銷毀shared_ptr
5)銷毀臨時CipString(str指向的)
這意味着:
EXPECT_EQ(static_cast<std::string>(*str), "Bye!");
變成不確定的行為
您可以重寫以下內容:
CipString str = *std::make_shared<CipString>("Bye!").get();
EXPECT_EQ(static_cast<std::string>(str), "Bye!");
如:
CipString str;
{
auto sp = std::make_shared<CipString>("Bye!");
str = *sp.get(); // here a copy is made (in original code copy initialization)
// here sp will get destroyed
}
// here str contains correct "Bye!" value
這沒有未定義的行為。 另一方面,此代碼:
CipString *str = std::make_shared<CipString>("Bye!").get();
將被重寫為:
CipString *str;
{
auto sp = std::make_shared<CipString>("Bye!");
str = sp.get(); // here a pointer is assigned to str, no copy is done as above
// here sp will get destroyed, and also pointer to
// which str points will be a dangling pointer
}
// here str should not be used - as it is UB
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.