Вы могли использовать обертку вокруг исходного массива (который является IList), как в этой (непротестированной) части кода.
public class SubList<T> : IList<T>
{
#region Fields
private readonly int startIndex;
private readonly int endIndex;
private readonly int count;
private readonly IList<T> source;
#endregion
public SubList(IList<T> source, int startIndex, int count)
{
this.source = source;
this.startIndex = startIndex;
this.count = count;
this.endIndex = this.startIndex + this.count - 1;
}
#region IList<T> Members
public int IndexOf(T item)
{
if (item != null)
{
for (int i = this.startIndex; i <= this.endIndex; i++)
{
if (item.Equals(this.source[i]))
return i;
}
}
else
{
for (int i = this.startIndex; i <= this.endIndex; i++)
{
if (this.source[i] == null)
return i;
}
}
return -1;
}
public void Insert(int index, T item)
{
throw new NotSupportedException();
}
public void RemoveAt(int index)
{
throw new NotSupportedException();
}
public T this[int index]
{
get
{
if (index >= 0 && index < this.count)
return this.source[index + this.startIndex];
else
throw new IndexOutOfRangeException("index");
}
set
{
if (index >= 0 && index < this.count)
this.source[index + this.startIndex] = value;
else
throw new IndexOutOfRangeException("index");
}
}
#endregion
#region ICollection<T> Members
public void Add(T item)
{
throw new NotSupportedException();
}
public void Clear()
{
throw new NotSupportedException();
}
public bool Contains(T item)
{
return this.IndexOf(item) >= 0;
}
public void CopyTo(T[] array, int arrayIndex)
{
for (int i=0; i<this.count; i++)
{
array[arrayIndex + i] = this.source[i + this.startIndex];
}
}
public int Count
{
get { return this.count; }
}
public bool IsReadOnly
{
get { return true; }
}
public bool Remove(T item)
{
throw new NotSupportedException();
}
#endregion
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
for (int i = this.startIndex; i < this.endIndex; i++)
{
yield return this.source[i];
}
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
Example exObject = theInt; // implicitly created copy constructor takes place
// object implicitly created from int and then copied
// it is like
Example exObject = Example(theInt);
// so it uses sequence
// Example(int) -> Example(const Example&)
int theInt1 = ctr; // operator int()
Если ваш компилятор поддерживает оптимизацию конструктора копирования и оптимизацию возвращаемого значения, вы не заметите выполнения
Example(const Example&)
, но вы можете объявить конструктор копирования закрытым, чтобы понять, о чем я говорю.
Вы можете пройтись по этому коду с помощью отладчика (и / или поставить точку останова на каждый из ваших конструкторов и операторов), чтобы увидеть, какие из ваших конструкторов и операторов вызываются какими строками.
Поскольку вы не определили их явно, компилятор также создал скрытый / стандартный конструктор копирования и оператор присваивания для вашего класса. Вы можете определить их явно (как показано ниже), если хотите использовать отладчик, чтобы увидеть, где и когда они вызываются.
Example::Example(const Example& rhs)
: itsVal(rhs.itsVal)
{}
Example& operator=(const Example& rhs)
{
if (this != &rhs)
{
this->itsVal = rhs.itsVal;
}
return *this;
}
Я бы попробовал это на Linux или BSD, просто чтобы посмотреть, как это работает, из любопытства.
У меня очень приблизительное предположение о проблеме: Бьюсь об заклад, что Windows выполняет множество дополнительных проверок, чтобы убедиться, что не отображается конец файла. В прошлом в некоторых ОС возникали проблемы с безопасностью, которые позволяли пользователю mmap просматривать личные данные файловой системы или данные из других файлов в области сразу за концом карты, поэтому осторожность здесь - хорошая идея для разработчика ОС. . Таким образом, Windows может использовать гораздо более осторожный метод «копирование данных с диска в ядро, обнуление несопоставленных данных, копирование данных для пользователя» вместо гораздо более быстрого «копирования данных с диска на пользователя».
Попробуйте сопоставить данные непосредственно под конец файла, за исключением последних байтов, которые не помещаются в блок размером 64 КБ.
осуществляется неявным конструктором, который принимает int.Для этого также требуется наличие конструктора копирования для Example, даже если компилятору разрешено не копировать экземпляр.
int theInt1 = ctr; // here
Здесь используется неявное преобразование Example в unsigned int , предоставляемый оператором приведения.
Операторов приведения обычно избегают, поскольку они имеют тенденцию приводить к путанице в коде, и вы можете явно пометить конструкторы с одним аргументом, чтобы отключить неявные преобразования в тип вашего класса. В C ++ 0x также должна быть добавлена возможность явно отмечать операторы преобразования (так что вам понадобится static_cast для их вызова? - мой компилятор не поддерживает их, и все веб-ресурсы, похоже, сосредоточены на явном преобразовании в bool).
даже если компилятору разрешено опускать копирование экземпляра.int theInt1 = ctr; // here
Здесь используется неявное преобразование Example в unsigned int, предоставляемое оператором приведения.
Операторов приведения обычно избегают, поскольку они имеют тенденцию приводить к запутанному коду и вы можете пометить конструкторы с одним аргументом явно, чтобы отключить неявные преобразования в тип вашего класса. C ++ 0x также должен добавить возможность явно отмечать операторы преобразования (так что вам понадобится static_cast для их вызова? - мой компилятор не поддерживает их, и все веб-ресурсы, похоже, сосредоточены на явном преобразовании в bool).
даже если компилятору разрешено опускать копирование экземпляра.int theInt1 = ctr; // here
Здесь используется неявное преобразование Example в unsigned int, предоставляемое оператором приведения.
Операторов приведения обычно избегают, поскольку они имеют тенденцию приводить к запутанному коду и вы можете пометить конструкторы с одним аргументом явно, чтобы отключить неявные преобразования в тип вашего класса. C ++ 0x также должен добавить возможность явно отмечать операторы преобразования (так что вам понадобится static_cast для их вызова? - мой компилятор не поддерживает их, и все веб-ресурсы, похоже, сосредоточены на явном преобразовании в bool).
и вы можете пометить конструкторы с одним аргументом явным образом, чтобы отключить неявные преобразования в ваш тип класса. C ++ 0x также должен добавить возможность явно отмечать операторы преобразования (так что вам понадобится static_cast для их вызова? - мой компилятор не поддерживает их, и все веб-ресурсы, похоже, сосредоточены на явном преобразовании в bool). и вы можете пометить конструкторы с одним аргументом явным образом, чтобы отключить неявные преобразования в ваш тип класса. C ++ 0x также должен добавить возможность явно отмечать операторы преобразования (так что вам понадобится static_cast для их вызова? - мой компилятор не поддерживает их, и все веб-ресурсы, похоже, сосредоточены на явном преобразовании в bool).