为什么向量中的元素需要可复制构造?

时间:2015-11-14 08:38:31

标签: c++ vector auto-ptr

我有这个问题,因为我正在阅读import android.content.Context; import android.database.Cursor; import android.graphics.Point; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Display; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.FrameLayout; import android.widget.GridView; import android.widget.ImageView; import java.util.HashSet; import java.util.Set; import #####.chromio.com.#####.R; import #####.chromio.com.#####.polypicker.model.Image; import #####.chromio.com.#####.polypicker.utils.ImageInternalFetcher; public class EnhancedGallery extends AppCompatActivity implements View.OnScrollChangeListener{ public ImageInternalFetcher mImageFetcher; private ImageGalleryAdapter mGalleryAdapter; private Set<Image> mSelectedImages; Display display; Toolbar toolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_enhanced_gallery); toolbar = (Toolbar) findViewById(R.id.toolbar_transparent); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); mGalleryAdapter = new ImageGalleryAdapter(this); GridView galleryGridView = (GridView)findViewById(R.id.pp__gallery_grid); mSelectedImages = new HashSet<Image>(); mImageFetcher = new ImageInternalFetcher(this, 500); Cursor imageCursor = null; try { final String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.ImageColumns.ORIENTATION}; final String orderBy = MediaStore.Images.Media.DATE_ADDED + " DESC"; imageCursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null, null, orderBy); while (imageCursor.moveToNext()) { Uri uri = Uri.parse(imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA))); int orientation = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.ImageColumns.ORIENTATION)); mGalleryAdapter.add(new Image(uri, orientation)); } } catch (Exception e) { e.printStackTrace(); } finally { if(imageCursor != null && !imageCursor.isClosed()) { imageCursor.close(); } } galleryGridView.setAdapter(mGalleryAdapter); galleryGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { Image image = mGalleryAdapter.getItem(i); if (!containsImage(image)) { //addImage(image); } else { //removeImage(image); } // refresh the view to // mGalleryAdapter.getView(i, view, adapterView); mGalleryAdapter.notifyDataSetChanged(); } }); } @Override public void onScrollChange(View view, int i, int i1, int i2, int i3) { toolbar.setAlpha(getAlphaforActionBar(view.getScrollY())); } private int getAlphaforActionBar(int scrollY) { int minDist = 0,maxDist = 650; if(scrollY>maxDist){ return 255; } else if(scrollY<minDist){ return 0; } else { int alpha = 0; alpha = (int) ((255.0/maxDist)*scrollY); return alpha; } } class ViewHolder { ImageView mThumbnail; // This is like storing too much data in memory. // find a better way to handle this Image mImage; } public class ImageGalleryAdapter extends ArrayAdapter<Image> { public ImageGalleryAdapter(Context context) { super(context, 0); } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.enhanced_gallery_adapter, null); holder = new ViewHolder(); holder.mThumbnail = (ImageView) convertView.findViewById(R.id.pp__thumbnail_image); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } Image image = getItem(position); boolean isSelected = containsImage(image); convertView.setForeground(isSelected ? getResources().getDrawable(R.drawable.gallery_photo_selected) : null); if (holder.mImage == null || !holder.mImage.equals(image)) { mImageFetcher.loadImage(image.mUri, holder.mThumbnail); holder.mImage = image; } return convertView; } } public boolean containsImage(Image image) { return mSelectedImages.contains(image); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); return true; case R.id.action_settings: return true; } return super.onOptionsItemSelected(item); } } 的部分。它说auto_ptr无法保存在向量中,因为它具有破坏性的复制和赋值。我能以某种方式理解它,我能想到的一个例子就像auto_ptr会让我感到惊讶。但是,如果我小心翼翼地使用它并且不这样做,我可以将auto_ptr ap = vec[0]存储在向量中吗?有没有更深层次的原因我无法存储?也许内部向量的实现需要这样的假设:元素需要是可复制构造的吗?

感谢。

2 个答案:

答案 0 :(得分:0)

调整向量大小时,会将其元素复制到新的后备数组,这是使用复制构造函数的位置。如果你有一个足够新的编译器,请考虑使用std :: unique_ptr。

答案 1 :(得分:0)

因为vector必须在其存储中存储已构造的对象。因此,它必须将对象复制到自己的存储中。

也是确保scope-safety的向量,它必须复制/移动传递的对象。

请参阅push_back文档

std::vector::push_back
void push_back( const T& value );   (1)
void push_back( T&& value );    (2)     (since C++11)
  

将给定元素值追加到容器的末尾。

     

1)新元素初始化为值的副本。

     

2)将值移入新元素。

     

参数

     

value - 要追加的元素的值

     

类型要求

     
      
  • T必须符合CopyInsertable的要求才能使用重载

  •   
  • T必须符合MoveInsertable的要求才能使用重载

  •   

CopyInsertable ID定义为

  

指定可以在未初始化的存储中就地复制构造类型的实例。