假设一个包含std :: vector的结构,其项目类型为std :: pair。
struct block {
std::vector<std::pair<key_t, value_t>> items;
block(const Data& d) : items()
{
items = std::vector<std::pair<key_t, value_t>>(d.size_);
}
};
稍后在代码中,我为位置0处的向量赋值:
block<key_t, value_t> b(*this);
std::pair<key_t, value_t> item = std::pair<key_t, value_t>(k, v);
b.items[0] = item;
稍后在代码中,我想迭代向量并期望&bucket_item != NULL
仅在位置0处为真,因为我只在此位置指定了一个值。事实上,&bucket_item != NULL
总是如此。
for (std::pair<key_t, value_t> item : b.items)
{
if (&item != NULL)
{
...
}
}
我无法使用NULL值初始化向量,如下所示:
items = std::vector<std::pair<key_t, value_t>>(d.size_, NULL);
如何解决这个问题?
答案 0 :(得分:3)
看起来你有Java背景,C ++有点不同。
items = std::vector<std::pair<key_t, value_t>>(d.size_);
items
已使用其默认构造函数进行初始化。上面的行创建了另一个默认的初始化容器,并将其分配给items
,这是不必要的。
在:
b.items[0] = item;
您需要确保向量足够大,因为它不会在operator[]
中为您分配元素。可以b.items.push_front/back(item)
使用vector::insert
将其插入特定位置,例如b.items.insert(b.items.begin(), item)
。 push_xxx
和insert
会为新元素分配内存。
当你这样做时
for (std::pair<key_t, value_t> item : b.items)
{
if (&item != NULL)
迭代容器中的所有现有元素。 item
按值(与Java不同)存储在容器中,因此它存在于非NULL地址,并且不能等于NULL
。
但是,表达式for(std::pair<key_t, value_t> item : b.items)
会在堆栈上创建每个元素的副本(也在非NULL地址处),您可能希望for(std::pair<key_t, value_t>& item : b.items)
仅引用该元素而不是复制它(注意items
左侧的&符号)。如果您不打算在循环内修改item
,您可能也希望使用const
限定符来向代码的读者明确您的意图。例如for(std::pair<key_t, value_t> const& item : b.items)
。
因为你无论如何使用C++11
,你不必拼出容器元素的类型,只需使用auto
:
for (auto const& item : b.items)
// do something to item
答案 1 :(得分:2)
当您创建std::vector
len
,其长度为std::vector<T> tVec(len)
时,您正在创建一个vector
len
个T
默认构造的T
类型对象{1}}。如果要表示空值,则需要采用以下方法之一:
T
的标记值表示无效值。T
并使用nullptr
作为自然无效值。bool
周围打包一个包含struct block {
using OptionalPair_t = boost::optional<std::pair<key_t, value_t>>;
std::vector<OptionalPair_t> items;
block(const Data& d) : items(d.size_)
{
}
};
标记为无效的课程。最后一个选项由boost::optional
提供。这是使用它重写代码:
boost::optional
由于bool
为contextually convertible到for (auto& item : b.items)
{
if (item)
{
...
}
}
,您可以这样做:
import android.app.Activity;
import android.app.Fragment;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.example.example.R;
public class MainActivity extends Activity
{
private static final String LOG_TAG = MainActivity.class.getName();
private String[] menuItems;
private DrawerLayout drawerLayout;
private ListView drawerList;
private ActionBarDrawerToggle drawerToggle;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState != null) {
return;
}
menuItems = getResources().getStringArray(R.array.menu_items);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerList = (ListView) findViewById(R.id.menu);
drawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.menu_list_item, menuItems));
drawerList.setOnItemClickListener(new DrawerItemClickListener());
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
drawerToggle = new ActionBarDrawerToggle(
this,
drawerLayout,
R.string.drawer_open,
R.string.drawer_close
) {
public void onDrawerClosed(View view) {
super.onDrawerClosed(view);
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
invalidateOptionsMenu();
}
};
drawerLayout.setDrawerListener(drawerToggle);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
LoginFragment loginFragment = new LoginFragment();
getFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, loginFragment).commit();
}
}
@Override
protected void onPostCreate(Bundle savedInstanceState)
{
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
if (drawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void selectMenuItem(int position)
{
Fragment fragment = null;
switch (position) {
case 0:
fragment = new DialFragment();
break;
case 1:
fragment = new NumbersFragment();
break;
case 2:
fragment = new LoginFragment();
break;
}
getFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, fragment)
.commit();
drawerList.setItemChecked(position, true);
drawerLayout.closeDrawer(drawerList);
}
private class DrawerItemClickListener implements ListView.OnItemClickListener
{
@Override
public void onItemClick(AdapterView parent, View view, int position, long id)
{
selectMenuItem(position);
}
}
}
答案 2 :(得分:0)
我认为你在这里混合了一些定义。
std::vector
的元素不能是NULL
,因为它不是指针。它的防御性存在。
int arr[] = {1};
,arr[0]
可以为空吗?当然不是。为什么会这样?它是一个真正的整数,它将内存中的某个位置放在非空的位置。
如果你在std :: vector元素上迭代,那意味着它们存在,所以它们不能为空。
答案 3 :(得分:0)
NULL
或更好nullptr
可用于初始化指针值,但初始化没有任何意义,例如std::string
或std::pair<std::string, int>
如果您希望矢量为空,则可以使用:
std::vector<std::pair<key_t, value_t>> items;
或者,如果您想要n
默认构建的std::pair
,您可以使用:
std::vector<std::pair<key_t, value_t>> items(n);
答案 4 :(得分:0)
对真的是价值观的结合。因此,您必须定义您认为哪些值组合为您的对的NULL等效值。
然后,您可以使用以下构造函数初始化矢量:
std::vector<std::pair<key_t, value_t>> items(d.size_, make_pair(0,0)) ;
您只需要使用key_t和value_t的中性值替换0。
请注意,向量确实包含值,而对是值。所以没有NULL指针会显示缺少值。