簡體   English   中英

在不復制和使用移動語義的情況下初始化向量

[英]Initialize vector without copying and using move semantics

有沒有辦法在初始化向量時避免復制?

下面的代碼將產生以下 output。

#include <iostream>
#include <vector>
using namespace std;

struct Ticker {
    std::string m_ticker;
    
    Ticker() {
        std::cout << "Default constructor" << std::endl;
        }
    Ticker(const std::string& ticker) 
    : m_ticker(ticker)
    {
        std::cout << "Parametrized constructor" << std::endl;
    }
    Ticker(Ticker&& other) 
    {
        std::cout << "Move constructor" << std::endl;
        m_ticker = other.m_ticker;
        other.m_ticker = "";
    }
    Ticker(const Ticker& x) 
    {
        std::cout << "Copy constructor" << std::endl;
        m_ticker = x.m_ticker;
    }
    ~Ticker() 
    {
    std::cout << "Destructor" << std::endl;
    }
    
    friend std::ostream& operator << (std::ostream& os, const Ticker& dr);
};

std::ostream& operator << (std::ostream& os, const Ticker& dr)
{
  os << "|" << dr.m_ticker << "|";
   return os;
}
    

int main() {
  std::vector<Ticker> table = std::move(std::vector<Ticker>{std::move(Ticker("MSFT")), std::move(Ticker("TSL"))});
  for (const auto& row: table)
  {
    std::cout << row << std::endl;
  }
  return 0;
}

這會產生以下 output:

Parametrized constructor
Move constructor
Parametrized constructor
Move constructor
Copy constructor
Copy constructor
Destructor
Destructor
Destructor
Destructor
|MSFT|
|TSL|
Destructor
Destructor

有沒有辦法避免復制構造函數並就地初始化或只是移動而不復制?

如果你使用

std::vector<Ticker> table = std::vector<Ticker>{Ticker("MSFT"), Ticker("TSL")};

你會得到

Parametrized constructor
Parametrized constructor
Copy constructor
Copy constructor
Destructor
Destructor
|MSFT|
|TSL|
Destructor
Destructor

其中有 4 個構造函數調用,而不是您當前擁有的 6 個。 其中 2 個調用是針對Ticker("MSFT")Ticker("TSL")的,另外兩個副本是因為初始化列表將其中的元素存儲為const ,因此必須盡可能將它們復制到向量中' t 從const object 移動。

要獲得最少的 2 次構造函數調用,您需要使用emplace_back成員 function,例如

std::vector<Ticker> table;      // create empty vector
table.reserve(2);               // allocate space for 2 Tickers but create nothing
table.emplace_back("MSFT");     // directly construct from "MSFT" in the reserved space
table.emplace_back("TSL");      // directly construct from "TSL" in the reserved space

其中有 output

Parametrized constructor
Parametrized constructor
|MSFT|
|TSL|
Destructor
Destructor

如果你想要像std::vector<Ticker> table = std::vector<Ticker>{Ticker("MSFT"), Ticker("TSL")};這樣的語法 ,但沒有額外的開銷,您可以將emplace_back解決方案包裝在工廠 function 中,例如

template <typename T, typename... Args> 
auto make_vector(Args&&... args)
{
    std::vector<T> data;
    data.reserve(sizeof...(Args));
    (data.emplace_back(std::forward<Args>(args)), ...);
    return data;
}

然后你會像這樣使用它

auto table = make_vector<Ticker>("MSFT", "TSL");

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM