Возвратите ссылку константы или копию в функции метода get?

Что лучше как значение по умолчанию, для возврата копии (1) или ссылка (2) от функции метода get?

class foo {
public:
    std::string str () { // (1)
        return str_;
    }

    const std::string& str () { // (2)
        return str_;
    }

private:
    std::string str_;
};

Я знаю, 2) могло быть быстрее, но не имеют к должному к (N) RVO. 1) более безопасные касающиеся повисшие ссылки, но объект будет, вероятно, outlife, или ссылка никогда не хранится.

Каково Ваше значение по умолчанию, когда Вы пишете класс и (еще) не знаете, выпускает ли производительность и время жизни вопрос?

Дополнительный вопрос: игра изменяется, когда участник не является простой строкой, а скорее вектором?

41
задан Omnifarious 2 February 2010 в 07:24
поделиться

8 ответов

Мое правило - возвращать копию для простых базовых типов данных, таких как int, последовательность и т.д. Для немного более сложных структур, где копирование может быть более дорогостоящим (как вектор вы упомянули) я предпочитаю вернуть const-reference.

-121--1194597-

Вот одна реализация:

class Enum(set):
    def __getattr__(self, name):
        if name in self:
            return name
        raise AttributeError

Вот ее использование:

Animals = Enum(["DOG", "CAT", "HORSE"])

print(Animals.DOG)
-121--1756166-

Ну это действительно зависит от того, что вы ожидаете поведение , по умолчанию.

Ожидаете ли вы, что звонивший увидит изменения, внесенные в str_ неизвестные (какое слово!)? Тогда вам нужно передать обратно ссылку. Может быть хорошо, если вы можете иметь пересчитанный член данных и вернуть его.

Если предполагается, что вызывающий абонент получит копию, выполните 1).

22
ответ дан 27 November 2019 в 00:46
поделиться

Мое правило - это вернуть копию для простых основных данных типа данных, таких как Int, String и т. Д. Для более сложных структур, где копирование может быть дорожным (например, в качестве вектора вы упомянули) я предпочитаю возвращать Const-Reference.

18
ответ дан 27 November 2019 в 00:46
поделиться

Компилятор в этом случае не сможет выполнить (N)RVO. (названная) оптимизация возвращаемого значения - это оптимизация, при которой компилятор создает на месте возвращаемого значения переменные функции auto, чтобы избежать необходимости копирования:

std::string f()
{
   std::string result;
   //...
   return result;
}

Когда компилятор видит код, приведенный выше (и предполагая, что при наличии любого другого возвращаемого значения он также вернет переменную result), он знает, что переменная result имеет единственно возможную судьбу, которая будет скопирована поверх возвращаемого временного, а затем уничтожена. Компилятор может затем полностью удалить переменную result и использовать возвращаемое временное как единственную переменную. Я настаиваю: компилятор не удаляет возвращаемое временное, а удаляет переменную локальной функции. Возвращаемое временное требуется для выполнения соглашения о вызове компилятора.

Когда вы возвращаете член вашего класса, он должен существовать, а соглашение о вызове требует, чтобы возвращаемый объект находился в определенном месте (обычно это адрес стека). Компилятор не может создать атрибут метода над местоположением возвращаемого объекта, а также не может элиминировать создание копии.

10
ответ дан 27 November 2019 в 00:46
поделиться

Вот вам:

How to: Reference ASP.NET Master Page Content

Из статьи, похоже, что

If Master.SQLerror = Nothing Then
    InternalSQLErrLabel.Text = ("No Errors Reported")
End If

должен работать на вас.

Просто добавьте директиву MasterType, как описано выше, или вы можете получить ошибку преобразования типа. (Или вы могли бы использовать переменную вашего типа мастер-страницы вместо Master, как предлагает daRoBBie в своем ответе.)

Я создал тестовый веб-сайт только для того, чтобы проверить это, и это работает. Вот полный источник сайта :

Site1.Master :

<%@ Master Language="VB" AutoEventWireup="false" CodeBehind="Site1.master.vb" Inherits="WebApplication1.Site1" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        This is the Master Page content.
        <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
        </asp:ContentPlaceHolder>
    </div>
    </form>
</body>
</html>

Site1.Master.vb :

Public Partial Class Site1
    Inherits System.Web.UI.MasterPage

    Private _SQLerror As String

    Public Property SQLerror() As String
        Get
            Return _SQLerror
        End Get
        Set(ByVal value As String)
            _SQLerror = String.Empty
        End Set
    End Property
End Class

WebForm1.aspx :

<%@ Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/Site1.Master"
    CodeBehind="WebForm1.aspx.vb" Inherits="WebApplication1.WebForm1" %>

<%@ MasterType VirtualPath="~/Site1.Master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    This is the Content Page content.
    <asp:Label ID="InternalSQLErrLabel" runat="server" Text="Label"></asp:Label>
</asp:Content>

WebForm1.aspx.vb :

Public Partial Class WebForm1
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Master.SQLerror = Nothing Then
            InternalSQLErrLabel.Text = ("No Errors Reported")
        End If
    End Sub

End Class

-121--643148-

используйте оператор кавычек Oracle:

select q'#someone's quote#' from dual;

символ «#» может быть заменен любым символом

-121--4907830-

Если нет особой причины использовать тип значения в качестве возвращаемого значения, всегда возвращаю ссылку const. Если мне нужна (или, как ожидается, потребуется) копия (с возможностью записи), я добавляю ctor копирования и оператор назначения в возвращаемый класс, если он еще не доступен. Для использования думать о:

const MyClass & ref = container.GetAt( 1234 ); // need only reference
MyClass copy = container.GetAt( 1234 ); // get writable copy 

На самом деле это довольно прямо вперед, не так ли?

1
ответ дан 27 November 2019 в 00:46
поделиться

Если нет особой причины использовать тип значения в качестве возвращаемого значения, я всегда возвращаю запись Const. Если мне нужно (или ждать, чтобы понадобиться) a (regiable) копию, я добавляю Copy CTOR и оператор назначения в возвращенный класс, если он еще не доступен. Для использования думать о:

const MyClass & ref = container.GetAt( 1234 ); // need only reference
MyClass copy = container.GetAt( 1234 ); // get writable copy 

На самом деле это довольно прямо вперед, не так ли?

-121--1194601-

Возвращение ссылки на внутренние органы объекта как часть своего общедоступного интерфейса может быть запахом кода, если не прямая плохая конструкция.

Перед возвратом ссылки на внутренний объект в общедоступном интерфейсе дизайнер должен пауза. Это так пары пользователи вашего класса для части вашего дизайна. Часто это прямое ненужное, иногда это указывает на дальнейшую конструкторскую работу необходимую. Иногда надо, как отметил комментарии.

3
ответ дан 27 November 2019 в 00:46
поделиться
  1. , если это небольшой базовый тип - примитивы, такие как int и long, их оболочки и другие базовые вещи, такие как 'Point' - возвращают копию

  2. , если это строка , или любой другой сложный тип - вернуть ссылку.

0
ответ дан 27 November 2019 в 00:46
поделиться

Единственная проблема, которую я имею с возвращением Const-Reference, которая является чем-то, что я обычно делал для несущих типов, состоит в том, что нечего остановить абонента, удаляя «Const» Ness и Затем модифицируя значение.

Лично я бы предположил, что такой код - ошибка. Если они знают, что вы возвращаете ссылку и продолжаете выбросить конденс, то он на голове.

0
ответ дан 27 November 2019 в 00:46
поделиться

Я возвращаю ссылку, потому что строка кажется мне "не дешевой для копирования". Это сложный тип данных с динамическим управлением памятью и всем остальным.

Аргумент «если вы хотите, чтобы вызывающий абонент получил копию, вы должны возвращать по значению» является спорным, потому что он вообще не исключает копирование. Вызывающий по-прежнему может сделать следующее и в любом случае получить копию

string s = obj.str();

Вам нужно явно создать ссылку на вызывающей стороне, чтобы иметь возможность ссылаться на элемент данных сразу после этого - но зачем вам это делать? Определенно существует достаточно определяемых пользователем типов, которые дешевы для копирования

  • интеллектуальных указателей
  • итераторов
  • всех неклассовых типов.
7
ответ дан 27 November 2019 в 00:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: