下面是一些包含一些已創建Location物件并更新它們的代碼。然后它需要構造std::vector這些物件中的一個以傳遞給其他函式。
我構造vector看起來更清晰的方式,因為它是一個初始化串列并且是一行,而不是push_back在初始化一個空向量后使用 3 個呼叫。因為我們在構建時就已經知道要進入向量的所有元素。
但是,這會導致制作 2 個副本。是否有向量建構式或其他技術來初始化只有 1 個副本的向量?(我想制作 1 個副本,因為我仍然想使用本地物件)
struct Location
{
Location(int x, int y, const std::string & frame)
: x(x)
, y(y)
, frame(frame)
{
std::cout << "ctor" << std::endl;
}
Location(const Location & other)
: x(other.x)
, y(other.y)
, frame(other.frame)
{
std::cout << "copy ctor" << std::endl;
}
Location(Location && other)
: x(std::move(other.x))
, y(std::move(other.y))
, frame(std::move(other.frame))
{
std::cout << "move ctor" << std::endl;
}
int x;
int y;
std::string frame;
};
int main ()
{
// local objects
Location l1 {1, 2, "local"};
Location l2 {3, 4, "global"};
Location l3 {5, 6, "local"};
// code that updates l1, l2, l3
// .
// .
// .
// construct vector
std::vector<Location> pointsVec {l1, l2, l3}; // 2 copies per element
std::vector<Location> pointsVec1;
pointsVec1.push_back(l1);
pointsVec1.push_back(l2);
pointsVec1.push_back(l3); // 1 copy per element
return 0;
}
編輯:這個問題通常適用于復制成本高昂的物件。向這個結構添加一個字串來證明這一點
編輯:添加示例移動 ctor
uj5u.com熱心網友回復:
初始化串列意味著一個副本。沒有辦法解決這個問題。
{std::move(l1), std::move(l2), std::move(l3)}您可以通過在初始化程式中寫入來替換兩個副本中的一個。請注意,由于您Location定義了一個自定義復制建構式,因此它實際上沒有移動建構式,并且將回退到副本。
如果要避免所有副本,則必須將元素一一移動到向量中。
std::vector<Location> pointsVec;
pointsVec.reserve(3); // or else you get more copies/moves when the vector rellocates
pointsVec.push_back(std::move(l1));
pointsVec.push_back(std::move(l2));
pointsVec.push_back(std::move(l3));
但讓我們面對現實吧:你的小班是 2 ints 大。副本沒有真正的成本(并且在復制方面沒有優勢),我的意思是字面意思:很有可能,編譯器只會優化所有的復制。
uj5u.com熱心網友回復:
是否有向量建構式或其他技術來初始化只有 1 個副本的向量?
如果將本地物件移動到陣列中,則可以從該陣列構造向量,例如:
// local objects
Location locs[3]{ {1, 2}, {3, 4}, {5, 6} };
// code that updates locs ...
// construct vector
std::vector<Location> pointsVec {locs, locs 3};
在線演示
另一種選擇是完全擺脫本地物件,在vector開始時在內部構造它們,然后只參考這些元素,例如:
// construct vector
std::vector<Location> pointsVec{ {1, 2}, {3, 4}, {5, 6} };
// local objects
Location &l1 = pointsVec[0];
Location &l2 = pointsVec[1];
Location &l3 = pointsVec[2];
// code that updates l1, l2, l3 ...
uj5u.com熱心網友回復:
如果你想要Location向量內的所有三個物件,并且你想要它們在L1, L2, 中L3,你肯定需要制作一個副本——三個物件不能在六個位置,每個位置兩次。
如果您之后不需要本地代碼中的l1, l2,l3實體,則可以通過在向量初始化中放置它們來移動它們。std::move()然而,這是一個很大的風險,因為變數似乎仍然存在,并且您以后可能會添加訪問它們的代碼,這會產生丑陋的后果。
更好的方法是在向量??初始化呼叫中直接構造它們,而不是制作臨時變數:
{{1,2},{3,4},{5,6}};.
uj5u.com熱心網友回復:
對于這種情況,您可以使用 , 的組合reserve來避免由于向量元素的重新分配而導致的復制emplace_back,因此您最終會得到 3 個新結構,但沒有副本:
[演示]
std::vector<Location> pointsVec1;
pointsVec1.reserve(3);
pointsVec1.emplace_back(l1.x, l1.y);
pointsVec1.emplace_back(l2.x, l2.y);
pointsVec1.emplace_back(l3.x, l3.y); // 1 ctor per element
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/430111.html
